花费为边权的亦或值
洛谷4366
link
给出m条边,它们之间的权重。
然后任意两点之间可以通过,花费为节点编号的亦或值。
题解
通过值的拆解,建立新的图来求解
3^6 = 5 = (4+1)
(3^7)+(7^6) = 4+1
那么连边的节点为(3^4)和(6^1),//亦或的结合律
题解报告
ac code
建立新的图然后跑最短路就可以了
亦或的最短路、最长路
亦或求最长路
亦或求最短路
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| #include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<algorithm> #include<queue> using namespace std; typedef long long ll; const int N=100005; int n,m; int head[N],tot; struct aa { int to,pre;ll dis; }edge[N*2]; void addedge(int u,int v,ll d) { edge[++tot].to=v;edge[tot].pre=head[u];edge[tot].dis=d;head[u]=tot; } int dfn[N],cnt; ll f[N],tmp[N*2],num; void dfs(int u,int fa) { dfn[u]=++cnt; for (int v,i=head[u];i;i=edge[i].pre) if ((v=edge[i].to)!=fa) { if (dfn[v]==0) { f[v]=f[u]^edge[i].dis; dfs(v,u); } else tmp[++num]=f[u]^f[v]^edge[i].dis; } } ll b[65]; int main() { scanf("%d%d",&n,&m); int u,v;ll d; for (int i=1;i<=m;i++) { scanf("%d%d%I64d",&u,&v,&d); addedge(u,v,d); addedge(v,u,d); } dfs(1,0); for (int i=1;i<=num;i++) { for (int j=62;j>=0;j--) if ((tmp[i]>>j)&1) { if (b[j]) tmp[i]^=b[j]; else {b[j]=tmp[i];break;} } } for (int i=62;i>=0;i--) if ((f[n]^b[i])<f[n]) f[n]=f[n]^b[i]; printf("%I64d",f[n]); return 0; }
|
未解决的问题