• 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
    ", 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
  • 相关阅读:
    作为一名程序员应该具备哪些素质
    从100万个整数里找出100个最大的数
    数据库 SQL语句优化
    服务器上文件打包下载
    ThreadPoolExcutor
    几种序列化与get、set方法的关系
    idea没有错误出现红色波浪线怎么去掉?
    两个对象的属性赋值
    RandomStringUtils的使用
    IDEA中类似eclipse的workSpace的实现
  • 原文地址:https://www.cnblogs.com/khan724/p/4373401.html
Copyright © 2020-2023  润新知