poj 2186 强连通

来源:互联网 发布:淘宝宝贝销售属性 编辑:程序博客网 时间:2024/05/04 06:41

题目链接:http://poj.org/problem?id=2186

题目大意:奶牛们又开始得瑟了,他们想知道究竟哪只牛(或者说是多少只。。)在牛们中最知名,如果a觉得b出名,b觉得c出名,那么a也会觉得c出名。。

题目思路:用tarjan求解的,先缩点之后建立一个新图,然后判断出度为零的点是否有且只有一个,如果是的话就输出属于这个强连通分量的点的个数,不是的话就输出零。

AC代码:

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <set>#include <map>#include <string>#include <cmath>#include <cstdlib>#include <ctime>using namespace std;#define mem(a,b) memset((a),(b),sizeof((a)))void RI (int& x){    x = 0;    char c = getchar ();    while (c == ' '||c == '\n')    c = getchar ();    bool flag = 1;    if (c == '-'){        flag = 0;        c = getchar ();    }    while (c >= '0' && c <= '9'){        x = x * 10 + c - '0';        c = getchar ();    }    if (!flag)    x = -x;}void RII (int& x, int& y){RI (x), RI (y);}void RIII (int& x, int& y, int& z){RI (x), RI (y), RI (z);}const int maxn = 11000;const int maxm = 55000;int n,m;struct Side{    int u,v,next;}side[maxm];int top,node[maxn];int t,dfn[maxn],low[maxn],sum;stack<int>s;void add_side(int u,int v){    side[top] = (Side){u,v,node[u]};    node[u] = top++;}void init(){    memset(node,-1,sizeof(node));    memset(dfn,0,sizeof(dfn));    top=sum=t=0;}void dfs(int u){    dfn[u]=low[u]=++t;    s.push(u);    for(int i=node[u];i!=-1;i=side[i].next){        int v=side[i].v;        if(!dfn[v])dfs(v);        if(dfn[v]!=-1)low[u]=min(low[u],low[v]);    }    if(low[u]==dfn[u]){        int v;        do{            v=s.top();s.pop();            dfn[v]=-1;            low[v]=sum;        }while(v!=u);        sum++;    }}int in[maxn];void build(){    int tmp = top;    top = 0;    mem(node,-1);    mem(in,0);    for(int i = 0;i < tmp;i ++){        if(low[side[i].u] != low[side[i].v]){            in[low[side[i].v]] ++;            add_side(low[side[i].u],low[side[i].v]);//cout<<low[side[i].u]<<' '<<low[side[i].v]<<endl;        }    }    //for(int i = 0;i < sum;i ++)cout<<in[i]<<' ';cout<<endl;}int get(int ss){    int ans = 0;    for(int i = 1;i <= n;i ++){        if(low[i] == ss)ans ++;    }    return ans;}int main(){    //freopen("test.txt","r",stdin);    while(~scanf("%d%d",&n,&m)){        init();        while(m --){            int a,b;            RII(a,b);            add_side(b,a);//cout<<b<<' '<<a<<endl;        }        for(int i = 1;i <= n;i ++){            if(!dfn[i])dfs(i);        }        //for(int i = 1;i <= n;i ++)cout<<low[i]<<' ';cout<<endl;        build();        int ss;        int num = 0;        for(int i = 0;i < sum;i ++){            if(in[i] == 0){ss = i;num ++;}        }        if(num > 1)cout<<0<<endl;        else {            cout<<get(ss)<<endl;        }    }    return 0;}


0 0