1 条题解
-
0
又来了又来了,又是思维 800 代码 2800。别放这种题了好不好求求你了欧内该/dk
首先有几个很显然的结论:
如果有一条路径经过一个权值 xor 不是 0 的环,则一定无解(可以无限绕这个环)
如果有一条路径经过一个权值 xor 是 0 的环,则该路径 xor 必须是 0 否则无解(同理)
考虑如何处理这样的环,发现很自然可以考虑 dfs 树,在树上打一个 tag 表示从树根到现在的位置的 xor,然后判断 dfs 树上的返祖边和这条边的起点与终点的 xor 即可处理出这些环,再从根往下 dfs 一次即可判断到终点的路径是否存在无解情况。
处理掉环之后剩下的有解情况一定是一张 dag(xor 是 0 的环可以等同于不可以经过),在其之上求出答案是简单的。
精细实现的话可以做到 ,有点懒就写了 ,无伤大雅啦。
#include<bits/stdc++.h> using namespace std; #define LL long long struct edge{ LL to,nt,val; }a[200005],b[200005]; LL n,i,j,k,m,cnt=0,t,x,y,z,cnt1=0; LL nxt[200005],num[200005],depth[200005],deg1[200005],deg2[200005],nxt1[200005]; LL fa[200005][22]; LL val1[200005],val2[200005],tmp1[200005],tmp2[200005],fa1[200005]; bool flag[200005],vis[200005],tag[200005],flag1[200005],flag2[200005],flag3[200005],flag4[200005]; queue<LL> q; stack<LL> st1[200005],st2[200005]; void add(LL x,LL y,LL z){ a[++cnt].to=y;a[cnt].nt=nxt[x];nxt[x]=cnt;a[cnt].val=z; } void add1(LL x,LL y,LL z){ b[++cnt1].to=y;b[cnt1].nt=nxt1[x];nxt1[x]=cnt1;b[cnt1].val=z; } LL father(LL x){ if(fa1[x]==x) return x; else return fa1[x]=father(fa1[x]); } bool check(LL x,LL y){ if(depth[x]<depth[y]) return false; LL num=depth[x]-depth[y]; for(LL i=0;i<=20;i++) if(num&(1ll<<i)) x=fa[x][i]; if(x==y) return true; else return false; } void update(LL x,LL y,LL val){ if(flag2[x]==true) flag2[y]=true; if(flag3[x]==true) flag3[y]=true; if(tmp1[x]!=-1){ if(tmp1[y]!=-1 && (tmp1[x]^val)!=tmp1[y]) flag3[y]=true; if(tmp1[y]==-1) tmp1[y]=tmp1[x]^val; } if(tmp2[x]!=-1){ if(tmp2[y]!=-1 && (tmp2[x]^val)!=tmp2[y]) flag2[y]=true; if(tmp2[y]==-1) tmp2[y]=tmp2[x]^val; } } void dfs(LL x){ for(LL i=nxt[x];i;i=a[i].nt) if(flag[a[i].to]==false){ flag[a[i].to]=true,num[a[i].to]=num[x]^a[i].val,depth[a[i].to]=depth[x]+1; vis[i]=true; LL now=x;fa[a[i].to][0]=x; for(LL j=1;j<=20;j++) now=fa[now][j-1],fa[a[i].to][j]=now; dfs(a[i].to); } } void dfs1(LL x){ if(x==y){ return ; } for(LL i=nxt[x];i;i=a[i].nt){ if(flag[a[i].to]==false && flag1[a[i].to]==false) flag[a[i].to]=true,dfs1(a[i].to); if(tag[a[i].to]==true && flag1[a[i].to]==false) tag[x]=true,deg1[a[i].to]++,deg2[x]++; } } LL dfs2(LL fath,LL x){ LL maxx=0; for(LL i=nxt[x];i;i=a[i].nt){ if(vis[i]==true){ maxx=max(maxx,dfs2(x,a[i].to)); } else{ if(check(x,a[i].to)==true){ maxx=max(maxx,depth[x]-depth[a[i].to]+1); if((num[x]^a[i].val)!=num[a[i].to]) flag2[x]=true; } } } if(maxx>0){ flag1[x]=true; if(maxx>1) fa1[x]=fath; maxx--; } return maxx; } void doit(LL x){ if(flag1[x]==true){ if(flag3[x]==true) flag2[x]=true; if(tmp1[x]!=-1 && tmp2[x]!=-1 && tmp1[x]!=tmp2[x]) flag2[x]=true; if(tmp1[x]!=-1) tmp2[x]=tmp1[x]; tmp1[x]=-1; } } void dfs4(LL x){ doit(x); for(LL i=nxt[x];i;i=a[i].nt){ if(vis[i]==true) st1[x].push(i); else if(check(x,a[i].to)==false) st2[x].push(i); } while(!st2[x].empty()){ update(x,a[st2[x].top()].to,a[st2[x].top()].val),doit(a[st2[x].top()].to); st2[x].pop(); } while(!st1[x].empty()){ update(x,a[st1[x].top()].to,a[st1[x].top()].val); doit(a[st1[x].top()].to); dfs4(a[st1[x].top()].to); st1[x].pop(); } } void dfs5(LL x){ if(flag2[x]==true) flag2[y]=true; for(LL i=nxt1[x];i;i=b[i].nt) if(flag4[b[i].to]==false){ flag4[b[i].to]=true;dfs5(b[i].to); } } int main(){ scanf("%lld",&t); while(t--){ cnt=0,cnt1=0; for(i=1;i<=n;i++){ nxt[i]=nxt1[i]=depth[i]=num[i]=deg1[i]=deg2[i]=val1[i]=val2[i]=tmp1[i]=tmp2[i]=0; flag[i]=tag[i]=false,flag1[i]=flag2[i]=flag3[i]=flag4[i]=false; while(!st1[i].empty()) st1[i].pop();while(!st2[i].empty()) st2[i].pop(); } for(i=1;i<=m;i++) vis[i]=false; for(i=1;i<=n;i++) for(j=0;j<=20;j++) fa[i][j]=0; scanf("%lld%lld",&n,&m); for(i=1;i<=n;i++) tmp1[i]=-1,tmp2[i]=-1; for(i=1;i<=m;i++){ scanf("%lld%lld%lld",&x,&y,&z),add(x,y,z),add1(y,x,z); } scanf("%lld%lld",&x,&y); tmp1[x]=0; flag[x]=true;dfs(x); for(i=1;i<=n;i++) fa1[i]=i; dfs2(0,x); for(i=1;i<=n;i++) if(flag2[i]==true) flag2[father(i)]=true; for(i=1;i<=n;i++) if(flag2[father(i)]==true) flag2[i]=true; dfs4(x); if(tmp2[y]>0) flag2[y]=true; dfs5(y); if(flag2[y]==true) printf("-1\n"); else{ for(i=1;i<=n;i++) flag[i]=false; tag[y]=true;flag[y]=true; dfs1(x);tag[x]=true; while(!q.empty()) q.pop(); q.push(x);val1[x]=1; while(!q.empty()){ LL tmp=q.front();q.pop(); for(LL i=nxt[tmp];i;i=a[i].nt) if(deg1[a[i].to]>0){ val1[a[i].to]^=val1[tmp]; deg1[a[i].to]--;if(deg1[a[i].to]==0) q.push(a[i].to); } } while(!q.empty()) q.pop(); q.push(y);val2[y]=1; while(!q.empty()){ LL tmp=q.front();q.pop(); for(LL i=nxt1[tmp];i;i=b[i].nt) if(deg2[b[i].to]>0){ val2[b[i].to]^=val2[tmp]; deg2[b[i].to]--;if(deg2[b[i].to]==0) q.push(b[i].to); } } LL ans=0; for(LL i=1;i<=n;i++) if(tag[i]==true){ for(LL j=nxt[i];j;j=a[j].nt) if(tag[a[j].to]==true && val1[i]==1 && val2[a[j].to]==1) ans^=a[j].val; } printf("%lld\n",ans); } } return 0; }
- 1
信息
- ID
- 11051
- 时间
- 3000ms
- 内存
- 512MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者