51Nod 1076 - 2条不相交的路径(边双连通分量-模板)

在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
const int maxn=100005;
vector<int> g[maxn];
bool is_cut[maxn];
int n,m,ans=0;//节点编号从1开始
int vis[maxn];//vis[u]记录u的边双连通分量的编号,从1开始
int low[maxn],dfn[maxn],pre[maxn];//pre[u]记录u的父亲节点编号
//dfn[u]记录节点u在DFS过程中被遍历到的次序号,low[u]记录节点u或u的子树通过非父子边追溯到最早的祖先节点(即DFS次序号最小

void tarjan(int u,int fu){
    pre[u]=fu;//记录当前u的父亲节点
    dfn[u]=low[u]=++ans;
    for(int i=0;i<g[u].size();i++){
        int v=g[u][i];
        if(!dfn[v]){
            tarjan(v, u);
            low[u]=min(low[u], low[v]);//先是得到一颗dfs树,回溯过程即後序遍历此dfs树,此时low[v]已經得到,因此可以通過low[v]來更新low[u]
        }else if(fu!=v){//如果v是u的父亲的话,即有重边,那么不可能是桥
            low[u]=min(low[u],dfn[v]);
        }
    }
}

void dfs(int x,int cnt){
    vis[x]=cnt;
    for(int i=0;i<g[x].size();i++){
        int v=g[x][i];
        if(vis[v] || is_cut[v] && is_cut[x]) continue;
        dfs(v,cnt);
    }
}

void solve(void){
    for(int i=1;i<=n;i++){
        if(!dfn[i]) tarjan(i, 0);
        int v=pre[i];
        if(dfn[v]<low[i] && v>0){
            is_cut[i]=is_cut[v]=1;
        }
    }
    int cnt=0;
    for(int i=1;i<=n;i++){
        if(!vis[i]){
            cnt++;
            dfs(i, cnt);
        }
    }
}

int main(){
    scanf("%d%d", &n, &m);
    for(int i=0;i<m;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        g[x].push_back(y);
        g[y].push_back(x);
    }
    solve();
    int q;
    scanf("%d", &q);
    while(q--){
        int u,v;
        scanf("%d%d",&u,&v);
        if(vis[u]==vis[v]) puts("Yes");
        else puts("No");
    }
    return 0;
}
posted @ 2019-02-17 21:19  不想吃WA的咸鱼  阅读(117)  评论(0编辑  收藏  举报