1076 两条不相交的路径
给出一个无向图G的顶点V和边E。进行Q次查询,查询从G的某个顶点V[s]到另一个顶点V[t],是否存在2条不相交的路径。(两条路径不经过相同的边)
(注,无向图中不存在重边,也就是说确定起点和终点,他们之间最多只有1条路)
Input
第1行:2个数M N,中间用空格分开,M是顶点的数量,N是边的数量。(2 <= M <= 25000, 1 <= N <= 50000) 第2 - N + 1行,每行2个数,中间用空格分隔,分别是N条边的起点和终点的编号。例如2 4表示起点为2,终点为4,由于是无向图,所以从4到2也是可行的路径。 第N + 2行,一个数Q,表示后面将进行Q次查询。(1 <= Q <= 50000) 第N + 3 - N + 2 + Q行,每行2个数s, t,中间用空格分隔,表示查询的起点和终点。
Output
共Q行,如果从s到t存在2条不相交的路径则输出Yes,否则输出No。
Input示例
4 4 1 2 2 3 1 3 1 4 5 1 2 2 3 3 1 2 4 1 4
Output示例
Yes Yes Yes No No
首先可以明确,两条不相交的路径组成一定可以构成一条环,又因为是无向图,则环上不小于三个点,所以可以找强联通,若查询时,这两个点属于同一个强联通子图则一定存在不止一条路径可以到达
#include <bits/stdc++.h> using namespace std; #pragma GCC diagnostic error "-std=c++11" vector<int>v[25006]; int n,m,x,y,q; int vis[250006],dnf[25006],low[25006]; int stacks[25006],belong[25006]; int ans=0,top=0,cnt=0; void tarjan(int now,int fa) { dnf[now]=low[now]=++ans; stacks[++top]=now; vis[now]=1; for(auto &t:v[now]) { if(!dnf[t]){ tarjan(t,now); low[now]=min(low[now],low[t]); } else{ if(vis[t] && t!=fa) low[now]=min(dnf[t],low[now]); } } if(low[now]==dnf[now]){ cnt++; int mid; do{ mid=stacks[top--]; belong[mid]=cnt; vis[mid]=0; }while(mid!=now); } } void dfs() { memset(dnf,0,sizeof(dnf)); memset(low,0,sizeof(low)); for(int i=1;i<=n;i++) if(!dnf[i]) tarjan(i,-1); } int main() { scanf("%d%d",&n,&m); for(int i=0,x,y;i<m;i++){ scanf("%d%d",&x,&y); v[x].push_back(y); v[y].push_back(x); } dfs(); scanf("%d",&q); while(q--) { scanf("%d%d",&x,&y); puts(belong[x]==belong[y]?"YES":"NO"); } return 0; }