[强联通分量_tarjan] PKU 1236 Network of Schools

和每日一题一样,只不过是给出每个顶点的邻接点,这里使用邻接表来做。

  1 # include <cstdio>
  2 # include <cstring>
  3 
  4 # define N (100 + 5)
  5 # define M ((N) * (N))
  6 
  7 int n, m;
  8 int top, cols, tmpdfn;
  9 int c[N], in[N], out[N], low[N], dfn[N], first[N], s[N];
 10 int u[M], v[M], next[M];
 11 char ins[N];
 12 
 13 int Min(int x, int y)
 14 {
 15     return x<y ? x:y;
 16 }
 17 
 18 void tarjan(int x)
 19 {
 20     dfn[x] = low[x] = ++tmpdfn;
 21     s[top++] = x;
 22     ins[x] = 1;
 23     for (int e = first[x]; e != -1; e = next[e])
 24     {
 25         int y = v[e];
 26         if (!dfn[y])
 27         {
 28             tarjan(y);
 29             low[x] = Min(low[x], low[y]);
 30         }
 31         else if (ins[y])
 32             low[x] = Min(low[x], dfn[y]);
 33     }
 34     
 35     if (low[x] == dfn[x])
 36     {
 37         ++cols;
 38         int t;
 39         do
 40         {
 41             t = s[--top];
 42             ins[t] = 0;
 43             c[t] = cols;
 44         } while (t != x);
 45     }
 46 }
 47 
 48 void cal(void)
 49 {
 50     top = 0, tmpdfn = 0, cols = 0;
 51     memset(dfn+1, 0, sizeof(int)*n);
 52     memset(ins+1, 0, sizeof(char)*n);
 53     for (int i = 1; i <= n; ++i) if (!dfn[i])
 54         tarjan(i);
 55 }
 56 
 57 void solve(void)
 58 {
 59     cal();
 60     if (cols == 1)
 61     {        
 62         printf("1\n0");
 63         return ;
 64     }
 65     memset(in+1, 0, sizeof(int)*cols);
 66     memset(out+1, 0, sizeof(int)*cols);
 67     for (int i = 0; i < m; ++i)
 68     {
 69         int x = u[i], y = v[i];
 70         if (c[x] != c[y])
 71         {
 72             ++out[c[x]];
 73             ++in[c[y]];
 74         }
 75     }
 76     int zin = 0, zout = 0;
 77     for (int i = 1; i <= cols; ++i)
 78     {
 79         if (!in[i]) ++zin;
 80         if (!out[i]) ++zout;
 81     }
 82     printf("%d\n%d", zin, zin>zout ? zin:zout);
 83 }
 84 
 85 void add(int x, int y)
 86 {
 87     u[m] = x;
 88     v[m] = y;
 89     next[m] = first[x];
 90     first[x] = m;
 91     ++m;
 92 }
 93 
 94 void read_graph(void)
 95 {
 96     m = 0;
 97     scanf("%d", &n);
 98     for (int i = 1; i <= n; ++i)
 99     {
100         first[i] = -1;
101         int x;
102         while (scanf("%d", &x), x)
103         { 
104             add(i, x);
105         }
106     }
107 }
108 
109 int main()
110 {    
111     read_graph();
112     solve();
113     
114     return 0;
115 }

单组数据。

原文地址:https://www.cnblogs.com/JMDWQ/p/2626530.html