poj 2762 Going from u to v or from v to u?(SCC缩点+拓扑排序)

判断图是否是单连通图。

强连通缩点后得到DAG图,然后拓扑排序,删点之后若形成1个以上入度为0的点,说明有超过1条链,不是单连通图。


#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<stack>
#include<cstring>
using namespace std;
#define maxn 1005
vector<int> G[maxn];
int pre[maxn],low[maxn],sccno[maxn],dfs_clock,scc_cnt;
stack<int> S;

void dfs(int u){
    pre[u]=low[u]=++dfs_clock;
    S.push(u);
    for(int i=0;i<G[u].size();++i){
        int v=G[u][i];
        if(!pre[v]){
            dfs(v);
            low[u]=min(low[u],low[v]);//用后代的low函数更新自身
        }
        else if(!sccno[v]){
            low[u]=min(low[u],pre[v]);//用反向边更新
        }
    }
    if(low[u]==pre[u]){
        ++scc_cnt;
        for(;;){
            int x=S.top();S.pop();
            sccno[x]=scc_cnt;
            if(x==u) break;
        }
    }
}

void find_scc(int n){
    dfs_clock=scc_cnt=0;
    memset(sccno,0,sizeof(sccno));
    memset(pre,0,sizeof(pre));
    for(int i=0;i<n;++i)
        if(!pre[i]) dfs(i);
}
int in[maxn],out[maxn];
vector<int> G2[maxn];
int main()
{
    int i,t,a,b,j,n,m;
    cin>>t;
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(i=0;i<n;++i) G[i].clear();
        for(i=1;i<=m;++i){
            scanf("%d%d",&a,&b);
            --a,--b;
            G[a].push_back(b);
        }
        find_scc(n);
        for(i=1;i<=scc_cnt;++i) {G2[i].clear();in[i]=0;}
        for(i=0;i<n;++i)
            for(j=0;j<G[i].size();++j)
            {
                int v=G[i][j];
                if(sccno[v]!=sccno[i]) {++in[sccno[v]];G2[sccno[i]].push_back(sccno[v]);}
            }
        int tot=0;
        for(i=1;i<=scc_cnt;++i)
            if(!in[i]) {S.push(i);++tot;}
        while(!S.empty()&&tot<2){
            int p=S.top();S.pop();
            tot=0;
            for(i=0;i<G2[p].size();++i){
                --in[G2[p][i]];
                if(in[G2[p][i]]==0){
                  ++tot;
                  S.push(G2[p][i]);
                }
            }
        }
        if(tot>1) puts("No");
        else puts("Yes");
        while(!S.empty())S.pop();
    }
    return 0;
}


你可能感兴趣的:(poj 2762 Going from u to v or from v to u?(SCC缩点+拓扑排序))