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

 

posted @ 2015-03-27 23:44  无道圣君  阅读(148)  评论(0编辑  收藏  举报