[强联通分量_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 }

单组数据。

你可能感兴趣的:(NetWork)