题目链接<http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5986>
题意:
给出一张图,两个起点和一个终点,问是否存在两条不相交的路。
题解:
先来个并查集,判断是否在一个连通块内。
再缩个点,如果都在一个点内,那么一定可以。
否则就是棵树,lca分类讨论一下。
赛上居然数组开小,疯狂自闭..
#include<iostream>
#include<cstdio>
#include<string.h>
#include<string>
#include<algorithm>
#include<stack>
#include<queue>
using namespace std;
const int M=2e5+7;
const int N=1e5+7;
int t,n,m,q;
struct Edge{
int v,nxt;
Edge(int v=0,int nxt=0):v(v),nxt(nxt){}
}edge[M*2],e[M*2];
int p[N],edn;
void add(int u,int v){
edge[++edn]=Edge(v,p[u]);p[u]=edn;
edge[++edn]=Edge(u,p[v]);p[v]=edn;
}
int dfn[N],low[N],bcc[N],bccnum,ind,st[N],top;
bool ef[M*2];
void tarjan(int u){
dfn[u]=low[u]=++ind;
st[++top]=u;
for(int i=p[u];~i;i=edge[i].nxt){
int v=edge[i].v;
if(ef[i]) continue;
ef[i]=ef[i^1]=1;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
/*if(dfn[u]<low[v]){
ef[i]=ef[i^1]=2;
}*/
}
else low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u]){
bccnum++;
while(1){
int x=st[top--];
bcc[x]=bccnum;
if(x==u) break;
}
}
}
int hd[M],ed;
void ad(int u,int v){
e[++ed]=Edge(v,hd[u]);hd[u]=ed;
}
void rebuild(){
memset(hd,-1,sizeof(hd));ed=-1;
for(int x=1;x<=n;x++){
int u=bcc[x];
for(int i=p[x];~i;i=edge[i].nxt){
int v=bcc[edge[i].v];
if(u==v) continue;
ad(u,v);
}
}
}
void init(){
memset(bcc,0,sizeof(bcc));bccnum=0;
memset(p,-1,sizeof(p));edn=-1;
memset(dfn,0,sizeof(dfn));
memset(ef,false,sizeof(ef));
top=ind=0;
}
int fa[N][20],d[N],dis[N];
void dfs(int u){
for(int i=hd[u];~i;i=e[i].nxt){
int v=e[i].v;
if(v==fa[u][0])continue;
d[v]=d[u]+1;
fa[v][0]=u;
dfs(v);
}
}
void initlca(){
for(int j=1;(1<<j)<=bccnum;j++){
for(int i=1;i<=bccnum;i++){
fa[i][j]=fa[fa[i][j-1]][j-1];
}
}
}
int lca(int a,int b){
if(d[a]>d[b])swap(a,b);
int f=d[b]-d[a];
for(int i=0;(1<<i)<=f;i++){
if((1<<i)&f) b=fa[b][i];
}
if(a!=b){
for(int i=(int)log2(N);i>=0;i--){
if(fa[a][i]!=fa[b][i]){
a=fa[a][i]; b=fa[b][i];
}
}
a=fa[a][0];
}
return a;
}
int ff[N];
int fd(int x){return x==ff[x]?x:ff[x]=fd(ff[x]);}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++) ff[i]=i;
init();
int u,v;
for(int i=1;i<=m;i++){
scanf("%d%d",&u,&v);
if(u==v) continue;
add(u,v);
int fu=fd(u),fv=fd(v);
ff[fu]=fv;
}
int ans=0;
for(int i=1;i<=n;i++){
if(!bcc[i]) tarjan(i);
}
rebuild();
memset(d,0,sizeof(d));
for(int i=1;i<=bccnum;i++){
if(!d[i]) dfs(i);
}
initlca();
int x,y,z;
while(q--){
scanf("%d%d%d",&x,&y,&z);
if(fd(x)!=fd(y)||fd(x)!=fd(z)){
printf("No\n");
continue;
}
x=bcc[x];y=bcc[y];z=bcc[z];
int pp=lca(y,z);
if((lca(pp,x)==pp||pp==x)&&(lca(x,y)==x||lca(x,z)==x)){
printf("Yes\n");
}
else printf("No\n");
}
}
}