poj 2186

 

  首先,强连通分量可以缩点,所有缩点后的图一定是一个有向无环图,出度为0的点受其他出度不为0的点的仰慕.因为要求的是受其他所有点仰慕的点的个数(强连通内互相仰慕),所以,当只有一个出度为0的点时,输出它所在的强连通分量的顶点个数就是答案.

  

  1 #include<cstdio>

  2 #include<cstring>

  3 #include<algorithm>

  4 #include<queue>

  5 #define _Clr(x, y) memset(x, y, sizeof(x))

  6 #define INF 0x3f3f3f3f

  7 #define N 10010

  8 using namespace std;

  9 

 10 struct Node

 11 {

 12     int to, next;

 13 }edge[N*5];

 14 int head[N], tot;

 15 int dfn[N], low[N];

 16 int Sta[N], bleg[N];

 17 int num[N], n;

 18 bool instack[N];

 19 int cnt, ght, top;

 20 

 21 void Init()

 22 {

 23     cnt=tot=ght=top=0;

 24     _Clr(head, -1);

 25     _Clr(dfn, 0);

 26     _Clr(instack, 0);

 27     _Clr(num, 0);

 28 }

 29 

 30 void Add_edge(int a, int b)

 31 {

 32     edge[tot].to = b;

 33     edge[tot].next = head[a];

 34     head[a] = tot++;

 35 }

 36 

 37 void dfs(int u)

 38 {

 39     dfn[u]=low[u]=++cnt;

 40     Sta[top++] = u;

 41     instack[u] = true;

 42     for(int i=head[u]; i!=-1; i=edge[i].next)

 43     {

 44         int v = edge[i].to;

 45         if(!dfn[v])

 46         {

 47             dfs(v);

 48             low[u] = min(low[u], low[v]);

 49         }

 50         else if(instack[v]) low[u] = min(low[u], dfn[v]);

 51     }

 52     if(low[u] == dfn[u])

 53     {

 54         ght++;

 55         int v;

 56         do

 57         {

 58             v = Sta[--top];

 59             instack[v] = false;

 60             bleg[v] = ght;

 61             num[ght]++;   //num[i]表示第i个强连通分量的顶点数

 62         }while(u!=v);

 63     }

 64 }

 65 

 66 int outdeg[N];

 67 void Tarjan()

 68 {

 69     for(int i=1; i<=n; i++)

 70         if(!dfn[i]) dfs(i);

 71 

 72     _Clr(outdeg, 0);

 73 

 74     // 缩点求出度

 75     for(int u=1; u<=n; u++)

 76     for(int i=head[u]; i!=-1; i=edge[i].next)

 77     {

 78         int v = edge[i].to;

 79         if(bleg[v]!=bleg[u]) outdeg[bleg[u]]++;

 80     }

 81 

 82     int ans=0, index;

 83     for(int i=1; i<=ght; i++)

 84         if(outdeg[i]==0)

 85             ans++, index=i;

 86     printf("%d\n", ans==1?num[index]:0);

 87 }

 88 

 89 int main()

 90 {

 91     int m, a, b;

 92     while(~scanf("%d%d", &n, &m))

 93     {

 94         Init();

 95         while(m--)

 96         {

 97             scanf("%d%d", &a, &b);

 98             Add_edge(a, b);

 99         }

100         Tarjan();

101     }

102     return 0;

103 }
View Code

 

你可能感兴趣的:(poj)