Try Again

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;
}

 

posted @ 2018-09-02 14:25  十年换你一句好久不见  阅读(742)  评论(0编辑  收藏  举报