题目大意:给一张无向图,求一条1-n的路径,是路径边权的异或和最小。
题解
这道题的思路很妙,首先我们可以随便找出一条从1到n的路径来,然后我们可以选一些环。
其实不管这个环和这条路径有怎样的关系,我们都是可以直接选的。
比如说选了一个和这个路径没有交的环,等价于从1走到了这个环然后走了一圈又走回到了1,一条边被异或两次相当于吗,没走。
对于和路径有交的环,异或上它相当于把有交的部分异或两次,相当于走了这个环,也是合法的。
然后我们把所有环插入线性基中,预处理可以用dfs实现。
代码
#include<iostream> #include<cstdio> #define N 100002 using namespace std; typedef long long ll; ll dis[N],tot,head[N],b[100],n,m; bool vis[N]; inline ll rd(){ ll x=0;char c=getchar();bool f=0; while(!isdigit(c)){if(c=='-')f=1;c=getchar();} while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();} return f?-x:x; } struct edge{int n,to;ll l;}e[N<<1]; inline void add(int u,int v,ll l){e[++tot].n=head[u];e[tot].to=v;e[tot].l=l;head[u]=tot;} inline void ins(ll x){ for(int i=62;i>=0;--i)if((1ll<<i)&x){ if(b[i])x^=b[i]; else{b[i]=x;return;} } } inline ll query(ll x){ for(int i=62;i>=0;--i)if((b[i]^x)>x)x^=b[i]; return x; } void dfs(int u){ vis[u]=1; for(int i=head[u];i;i=e[i].n){ int v=e[i].to; if(vis[v])ins(dis[u]^dis[v]^e[i].l); else dis[v]=dis[u]^e[i].l,dfs(v); } } int main(){ n=rd();m=rd();ll u,v,w; for(int i=1;i<=m;++i){ u=rd();v=rd();w=rd(); add(u,v,w);add(v,u,w); } dfs(1); printf("%lld ",query(dis[n])); return 0; }