poj2762 弱连通 缩点+ 拓扑排序

来源:互联网 发布:rsync linux 自动同步 编辑:程序博客网 时间:2024/05/21 11:01



题意:对于图的任意两点AB,或者A可达B,或者B可达A

解法: 缩点+拓扑排序



代码:


#include<cstdio>#include<cstring>#include<iostream>#include<queue>using namespace std;const int maxn=2110;bool map[maxn][maxn],map1[maxn][maxn];int dfn[maxn],low[maxn];int id[maxn];  //记录点属于哪个联通分量int cnt,top,indx;//cnt记录连通分量的个数和标号,top栈,index记录时间int stack[maxn];int n,m;int in[maxn];void tarjan(int u){    low[u]=dfn[u]=++indx;    stack[++top]=u;    for(int i=1;i<=n;++i){        if(map[u][i]){            if(!dfn[i]){                tarjan(i);                low[u]=min(low[u],low[i]);            }            else if(!id[i]) low[u]=min(low[u],dfn[i]);        }    }    if(low[u]==dfn[u]){        cnt++;        int v;        do{            v=stack[top];            id[v]=cnt;        }while(stack[top--]!=u);    }}void solve(){    indx=top=cnt=0;    memset(dfn,0,sizeof(dfn));    memset(id,0,sizeof(id));    for(int i=1;i<=n;++i){        if(!dfn[i]) tarjan(i);    }}int topo(){    queue<int> que;    int sum=0;    for(int i=1;i<=cnt;i++){        if(!in[i]){            sum++;            que.push(i);        }    }    if(sum>=2)        return 0;    for(int i=1;i<=cnt;i++){        int te=que.front();        que.pop();        sum=0;        for(int j=1;j<=cnt;j++){            if(map1[te][j]){                in[j]--;                if(!in[j]){                    sum++;                    que.push(j);                }            }        }        if(sum>=2) return 0;    }    return 1;}int main(){    int T;    cin>>T;    while(T--){        memset(map,0,sizeof(map));        memset(map1,0,sizeof(map1));        cin>>n>>m;        int u,v;        while(m--){            scanf("%d%d",&u,&v);            map[u][v]=1;        }        solve();        memset(in,0,sizeof(in));        for(int i=1;i<=n;++i)        for(int j=1;j<=n;++j){            if(map[i][j]){                if(id[i]!=id[j]){                    map1[id[i]][id[j]]=1;                    in[id[j]]++;                }            }        }        int ans=topo();        if(ans) cout<<"Yes"<<endl;        else cout<<"No"<<endl;    }    return 0;}


原创粉丝点击