Popular Cows POJ

来源:互联网 发布:网络进度计划要点 编辑:程序博客网 时间:2024/06/06 04:43

有向图中所有点都能到达的点

题意
题目大概是有好多牛,牛(们)之间具有某种关系(鬼知道),这种关系具有传递性,如果有 A欢迎B和B欢迎C,那么就有A欢迎C。我们要找到能让其他所有的牛都欢迎的牛。
思路
画图易知
如果强联通分量中有多个缩点,出度为零,要么不成联通,要么联通也不能被所有牛崇拜,故而本题求的是唯一的一个出度为零的连通分量的规模
Ps:对于入度没有要求(画蛇添足必须死)
代码

/* * Author       :  Echo * Email        :  1666424499@qq.com   * Description  :    * Created Time :  2017/10/15 17:54:39 * Last Modify  :  2017/10/15 19:03:40 * File Name    :  write.cpp */#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <string>using namespace std;const int maxn=1e5+100;const int maxm=1e6;const int INF=1e9;struct edge {    int to,next;}an[maxm];int head[maxn];int dfn[maxn]; //入栈时间戳int ins[maxn]; //是否入栈int low[maxn]; //最早发现时间int stk[maxn]; //手工栈int dot[maxn]; //缩点int out[maxn]; //出度int ind[maxn]; //入度int m=0;//edge int cntm;int top;//stackint cnt;//dotint n;//pointint tm;//timevoid addedge(int u,int v){    an[++cntm].to=v;    an[cntm].next=head[u];    head[u]=cntm;}void tarjan(int u){    dfn[u]=low[u]=++tm;    stk[++top]=u;    ins[u]=1;    for(int i=head[u];i!=-1;i=an[i].next){        int v=an[i].to;        if(dfn[v]==0){            tarjan(v);            if(low[u]>low[v]) low[u]=low[v];        }         else if(ins[v]&&low[u]>low[v]){            low[u]=low[v];        }    }    if(low[u]!=dfn[u]) return;    int v=stk[top--];    ins[v]=0;    dot[v]=++cnt;    while(u!=v){        v=stk[top--];        ins[v]=0;        dot[v]=cnt;    }}int main(){    //while(~scanf("%d",&n)){        scanf("%d%d",&n,&m);        top=cnt=tm=0;        for(int i=1;i<=n;i++){            dfn[i]=ins[i]=out[i]=ind[i]=0;            head[i]=-1;        }        for(int i=1;i<=m;i++){            int u,v;            scanf("%d%d",&u,&v);            addedge(u,v);        }        for(int i=1;i<=n;i++){            if(dfn[i]) continue;             tarjan(i);        }        for(int u=1;u<=n;u++){            for(int i=head[u];i!=-1;i=an[i].next){                int v=an[i].to;                if(dot[u]==dot[v])continue;                out[dot[u]]++;                ind[dot[v]]++;            }        }        int ans1=0,ans2=0,ans=0;        for(int i=1;i<=cnt;i++){            if(ind[i]==0) ans1++;            if(out[i]==0) ans2++;        }        if(ans2>1){            printf("0\n");            return 0;        }        for(int i=1;i<=n;i++){            if(out[dot[i]]) continue;            ans++;        }        printf("%d\n",ans);    //}    return 0;}
原创粉丝点击