和每日一题一样,只不过是给出每个顶点的邻接点,这里使用邻接表来做。
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 }
单组数据。