题目链接:zoj4097 Rescue the Princess
题意:给一个有可能有重边的无向图,问从v,w到u是否有不相交的路径。
题解:先边双联通分量缩点就会的得到一片森林,如果不在同一颗树里面肯定,no,在同一颗树里面分情况讨论一下
#include<bits/stdc++.h> #include<set> #include<cstdio> #include<iomanip> #include<iostream> #include<string> #include<cstring> #include<algorithm> #define pb push_back #define mk make_pair #define ll long long #define fi first #define se second #define PI 3.14159265 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define eps 1e-7 #define pii pair<int,int> #define pll pair<ll,ll> typedef unsigned long long ull; const int mod=998244353; const ll inf=0x3f3f3f3f3f3f3f; const int N=1e5+5; using namespace std; int n,m,q; vector<int>g[N],G[N]; int dfn[N],low[N],s[N],tot,cmp[N],scc_cnt,ind; bool vis[N],ins[N]; int belong[N]; int block=0; int tarjan(int v,int f,int b) { low[v]=dfn[v]=++ind; s[++tot]=v; ins[v]=1; vis[v]=1; belong[v]=b; int flag=0;//判断是否为重边 for(int to:g[v]) { if(f==to) { if(++flag<2)continue;//大于等于二时有重边 } if(!dfn[to]) { tarjan(to,v,b); low[v]=min(low[v],low[to]); } else if(ins[v])low[v]=min(low[v],low[to]); } if(low[v]==dfn[v]) { cmp[v]=++scc_cnt; while(s[tot]!=v)ins[s[tot]]=0,cmp[s[tot--]]=scc_cnt; ins[v]=0; tot--; } } int f[N][18],dep[N]; void dfs(int v,int fa,int d) { vis[v]=1; f[v][0]=fa; dep[v]=d; for(int to:G[v]) { if(to==fa)continue; dfs(to,v,d+1); } } int lca(int x,int y) { if(dep[x]<dep[y])swap(x,y); int k=dep[x]-dep[y]; for(int i=0;i<18;i++) { if((k>>i)&1)x=f[x][i]; } if(x==y)return y; for(int i=17;i>=0;i--) { if(f[x][i]!=f[y][i]) { x=f[x][i];y=f[y][i]; } } return f[x][0]; } void init() { for(int i=0;i<=scc_cnt;i++) { G[i].clear(); dep[i]=0; for(int j=0;j<18;j++)f[i][j]=0; } for(int i=0;i<=n;i++)vis[i]=low[i]=dfn[i]=0,g[i].clear(); scc_cnt=0;tot=0;ind=0;block=0; } int main() { int T; scanf("%d",&T); while(T--) { init(); scanf("%d %d %d",&n,&m,&q); for(int i=0;i<m;i++) { int x,y; scanf("%d %d",&x,&y); g[x].pb(y); g[y].pb(x); } for(int i=1;i<=n;i++) { if(!vis[i]) { tarjan(i,0,++block); } } for(int i=1;i<=n;i++) { for(int to:g[i]) { if(cmp[to]!=cmp[i]) { G[cmp[to]].pb(cmp[i]); } } } for(int i=1;i<=scc_cnt;i++)vis[i]=0; for(int i=1;i<=scc_cnt;i++) { if(!vis[i]) { dfs(i,0,0); } } for(int i=1;i<18;i++) { for(int j=1;j<=scc_cnt;j++) { f[j][i]=f[f[j][i-1]][i-1]; } } while(q--) { int u,v,w; scanf("%d %d %d",&u,&v,&w); if(belong[u]!=belong[v]||belong[v]!=belong[w]||belong[u]!=belong[w]) { printf("No ");continue; } u=cmp[u];v=cmp[v];w=cmp[w]; bool f1=1; int uv=lca(u,v),uw=lca(u,w),vw=lca(v,w); if(uv==u) { if(vw==u&&uw==u) ; else if(uw!=u); else f1=0; } else if(uv==v) { if(uw==u); else f1=0; } else { if(uw!=u)f1=0; } if(f1)printf("Yes "); else printf("No "); } } return 0; } /* 1 2 1 2 1 2 1 1 1 2 1 2 */