poj 2186 有向图的相连通分量

来源:互联网 发布:淘宝休闲零食数据 编辑:程序博客网 时间:2024/05/22 01:54

我想到tarjan强连通缩点,判断出度为0的那个点,是不是所有点都能到它。


不过网上的思路很厉害:只要求出所有强连通分量的出度,如果出度为0的只有1个的话,那么那个强连通分量里的点集就是答案。

为什么是出度为0只有1个呢?

若出度为0的有2个或以上,则这几个强连通分量之间就没有办法连接,显然没有答案。

若出度为0的只有1个,则其他强连通分量一定有边指向这个强连通分量,若没有,则一定还有1个强连通分量出度为0。

#include<iostream>#include<cmath>#include<cstdio>#include<sstream>#include<cstdlib>#include<string>#include<string.h>#include<cstring>#include<vector>#include<algorithm>#include<iterator>#include<queue>#include<ctime>#include<bitset>#define eps 1e-6#define INF 0x3f3f3f3f#define PI acos(-1.0)#define ll long long#define lson l,m,(rt<<1)using namespace std;#define MAXN 10010#define MAXM 200005struct node{    int to,next;}edge[MAXM];int head[MAXN],en;int low[MAXN],dfn[MAXN],stack[MAXN],top,set[MAXN],col,num;bool vis[MAXN],instack[MAXN];int NUM[MAXN];int out[MAXN];int n;int m;void addedge(int a,int b){    edge[en].to=b;    edge[en].next=head[a];    head[a]=en++;}void tarjan(int u){    vis[u]=1;    dfn[u]=low[u]=++num;    instack[u]=true;    stack[++top]=u;    for(int i=head[u];i!=-1;i=edge[i].next)    {        int v=edge[i].to;        if(!vis[v])        {            tarjan(v);            low[u]=min(low[u],low[v]);        }        else            if(instack[v])                low[u]=min(dfn[v],low[u]);    }    if(dfn[u]==low[u])    {        int j;        col++;        do        {            j=stack[top--];            instack[j]=false;            set[j]=col;            NUM[col]++;        }        while (j!=u);    }}void init(){    int i;    top=col=num=0;    memset(head,-1,sizeof(head));    memset(instack,0,sizeof(instack));    memset(vis,0,sizeof(vis));    memset(set,-1,sizeof(set));    memset(NUM,0,sizeof(NUM));}int main(){    int a,b;    while(~scanf("%d%d",&n,&m))    {        init();        for(int i=1;i<=m;i++)        {            scanf("%d%d",&a,&b);            addedge(a,b);        }        for(int i=1;i<=n;i++)            if(!vis[i])tarjan(i);        for(int i=1;i<=n;i++)        {            for(int j=head[i];j!=-1;j=edge[j].next)            {                if(set[i]!=set[edge[j].to])//若下个点不是当前强连通分量,那么出度+1                {                    out[set[i]]++;                }            }        }        int num=0;        int t;        for(int i=1;i<=col;i++)        {            if(!out[i])            {                num++;                t=i;            }        }        if(num!=1) cout<<0<<endl;        else cout<<NUM[t]<<endl;    }    return 0;}


4 0