码迷,mamicode.com
首页 > 其他好文 > 详细

tarjan求强连通+缩点——cf1248E

时间:2019-10-26 01:18:54      阅读:84      评论:0      收藏:0      [点我收藏+]

标签:tarjan   pac   bit   个数   ++   while   std   scanf   缩点   

这题好像是DEF里最水的,,

/*
建图:如果a认识b,那么从a->b连一条边,将点分成两个集合A,B,没有从A->B的边 
求出强连通分量,再造一张新图,新图中任取一个的出度为0的点作为集合A即可
*/
#include<bits/stdc++.h>
using namespace std;
#define N 2000005

struct Edge{int to,nxt;}e[N<<1];
int head[N],tot,n,m;

int c[N],out[N],cnt;//新图的点个数,每个点的出度 
int ind,dfn[N],low[N],stk[N],top,ins[N];
void tarjan(int x){
    dfn[x]=low[x]=++ind;
    stk[++top]=x;ins[x]=1;
    for(int i=head[x];i!=-1;i=e[i].nxt){
        int y=e[i].to;
        if(!dfn[y]){
            tarjan(y);
            low[x]=min(low[x],low[y]);
        }
        else if(ins[y])
            low[x]=min(low[x],dfn[y]);
    }
    if(dfn[x]==low[x]){
        cnt++;
        int y;
        do{
            y=stk[top--];
            ins[y]=0;
            c[y]=cnt;
        }while(x!=y);
    }
}

void init(){
    cnt=tot=ind=0;
    for(int i=0;i<=2*n;i++)
        low[i]=dfn[i]=ins[i]=out[i]=c[i]=0,head[i]=-1;
}
void add(int u,int v){
    e[tot].to=v;e[tot].nxt=head[u];head[u]=tot++;
}

int main(){
    int t;cin>>t;while(t--){
        cin>>n>>m;
        init();
        for(int i=1;i<=m;i++){
            int u,v;scanf("%d%d",&u,&v);
            if(u!=v)add(u,v);    
        }
        
        for(int i=1;i<=n;i++)
            if(!dfn[i])tarjan(i);
        
         for(int u=1;u<=n;u++)
            for(int i=head[u];i!=-1;i=e[i].nxt){
                int v=e[i].to;
                if(c[u]!=c[v])
                    out[c[u]]++;
            }
            
        int ans=0;
        for(int i=1;i<=cnt;i++)
            if(out[i]==0){ans=i;break;}
        if(ans==0||cnt==1){puts("No");continue;}
        
        puts("Yes");
        int cnta=0,cntb=0;
        for(int i=1;i<=n;i++)
            if(c[i]==ans)cnta++;
            else cntb++;
        cout<<cnta<<" "<<cntb<<\n;
        for(int i=1;i<=n;i++)if(c[i]==ans)cout<<i<<" ";puts("");
        for(int i=1;i<=n;i++)if(c[i]!=ans)cout<<i<<" ";puts("");
    }
}
/*
9 21
1 7
5 7
4 8
1 1
4 4
7 3
3 3
6 3
6 6
5 5
7 7
8 2
9 2
3 1
8 8
9 9
2 2
1 5
6 7
2 6
6 4

*/

 

tarjan求强连通+缩点——cf1248E

标签:tarjan   pac   bit   个数   ++   while   std   scanf   缩点   

原文地址:https://www.cnblogs.com/zsben991126/p/11741372.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!