poj 1236 - Network of Schools

题目来源: http://acm.pku.edu.cn/JudgeOnline/problem?id=1236

 

这是一道强连通分量的题目。

题意: 

网络中有一些学校,每个学校可以分发软件给其他学校。可以向哪个分发取决于他们各自维护的一个清单。

有两个问题,1:至少要copy多少份新软件给那些学校, 才能使得每个学校都能得到。

2:要在所有的学校的清单里面至少一共增加几项才能 使得  把软件给任意一个学校,所有的学校都能收得到。

 

思路: 

       整个就是一个有向图啊, 学校是节点, 它的表里面有从他出发到其他节点的边。

       问题一: 要使每个学校都能收到,就是计算图里面一共有多少入度是0的点,这个好理解。

      问题二: 先学习下计算强连通分支的算法——Tarjan,  然后缩点,把每一块看成一个点,出来一个新的有向图。然后计算出度为0的入度为0的点各有多少, 大的那个就是答案。 

值得注意的是, 当只有一个强连通分支的时候,就是缩点后只有一个点,虽然入度出度为0的都有一个,但是实际上不需要增加清单的项了,所以答案是1,0;

 

 

 

1 #include <iostream>
2  using namespace std;
3
4  const int M = 105;
5
6  struct Node
7 {
8 int to;
9 Node *next;
10 };
11 Node *g[M];
12 int low[M], stack[M], ord[M], id[M];
13 int cnt, scnt;
14 bool instack[M], map[M], in[M], out[M];
15
16
17
18 void init(int n)
19 {
20 for(int i=1; i<=n; i++)
21 {
22 in[i] = true;
23 out[i] = true;
24 low[i] = 0;
25 ord[i] = 0;
26 id[i] = 0;
27 instack[i] = false;
28 map[i] = true;
29 }
30 }
31
32 void insert(int u, int v)
33 {
34 Node *tmp = new Node;
35 tmp -> to = v;
36 tmp -> next = g[u];
37 g[u] = tmp;
38 }
39
40 void Tarjan(int n, int e)
41 {
42 cnt++;
43 low[e] = ord[e] = cnt;
44 instack[e] = true;
45 stack[++stack[0]] = e;
46 Node *tmp = g[e];
47
48 while (tmp != NULL)
49 {
50 int t = tmp -> to;
51 if(!ord[t])
52 {
53 Tarjan(n, t);
54 if(low[e] > low[t])
55 low[e] = low[t];
56 }
57 else if(instack[t] && ord[t]<low[e])
58 low[e] = ord[t];
59
60 tmp = tmp -> next;
61 }
62
63 if(low[e] == ord[e])
64 {
65 int t;
66 scnt++;
67 do
68 {
69 t = stack[stack[0]--];
70 id[t] = scnt;
71 instack[t] = false;
72
73 }while (t != e);
74 }
75
76 return ;
77 }
78
79 void find_compentents(int n)
80 {
81 cnt = scnt = 0;
82 stack[0] = 0;
83 for(int i=1; i<=n; i++)
84 {
85 if(!ord[i])
86 Tarjan(n, i);
87 }
88 return ;
89 }
90
91 int main()
92 {
93 int n;
94 while (scanf("%d",&n)!=EOF)
95 {
96 init(n);
97 for(int i=1; i<=n; i++)
98 {
99 while (1)
100 {
101 int a;
102 scanf("%d",&a);
103 if(a == 0)
104 break;
105 // out[i] = false;
106 // in[a] = false;
107 insert(i, a);
108 }
109 }
110
111 find_compentents(n);
112
113 int ansin = 0, ansout = 0;
114 for(int i=1; i<=n; i++)
115 {
116 Node *tmp;
117 tmp = g[i];
118 while (tmp != NULL)
119 {
120 int e = tmp -> to;
121 if(id[i]!=id[e] && out[id[i]])
122 out[id[i]] = false;
123 if(id[i]!=id[e] && in[id[e]])
124 in[id[e]] = false;
125 tmp = tmp -> next;
126 }
127 }
128
129 for(int i=1; i<=scnt; i++)
130 {
131 if(in[i])
132 ansin ++;
133 if(out[i])
134 ansout ++;
135 }
136
137 if(scnt == 1)
138 ansout = 0;
139 else
140 ansout = ansout>ansin ? ansout:ansin;
141 printf("%d\n%d\n",ansin,ansout);
142
143
144 }
145 return 0;
146 }
147

 

 

 

 

posted @ 2010-05-22 11:06  六少  阅读(803)  评论(2编辑  收藏  举报