poj~1236 Network of Schools 强连通入门题
一些学校连接到计算机网络。这些学校之间已经达成了协议:
每所学校都有一份分发软件的学校名单(“接收学校”)。
请注意,如果B在学校A的分发名单中,则A不一定出现在学校B的名单中
您需要编写一个计划,计算必须接收新软件副本的最少学校数量,
以便软件根据协议(子任务A)到达网络中的所有学校。作为进一步的任务,
我们希望确保通过将新软件的副本发送到任意学校,该软件将覆盖网络中的所有学校。
为了实现这一目标,我们可能需要扩大新成员的接收者名单。
计算必须做的扩展的最小数目,以便我们发送新软件的任何学校,
它将到达所有其他学校(Subtask B)。
一种扩展意味着将一名新成员引入一所学校的接收者名单。
这题强连通水题 ,模板题目,
第一问求出最少要几个点才能到任意点
其实就是一个强连通缩点后,求出有几个入度为0的点,
第二问求出要加上几条边把所点后的有向无环图变成一个强连通图
就是求 max(sumin, sumout)
1 #include <cstdio> 2 #include <cstring> 3 #include <string> 4 #include <algorithm> 5 #include <queue> 6 using namespace std; 7 8 const int maxn = 1e5 + 10; 9 int n, m, u, v, tot, top, cnt, flag; 10 struct node { 11 int v, next; 12 } edge[maxn]; 13 int head[maxn], instack[maxn], s[maxn]; 14 int dfn[maxn], low[maxn], belong[maxn]; 15 void init() { 16 tot = cnt = top = flag = 0; 17 memset(s, 0, sizeof(s)); 18 memset(head, -1, sizeof(head)); 19 memset(dfn, 0, sizeof(dfn)); 20 memset(instack, 0, sizeof(instack)); 21 } 22 void add(int u, int v) { 23 edge[tot].v = v; 24 edge[tot].next = head[u]; 25 head[u] = tot++; 26 } 27 void tarjin(int v) { 28 dfn[v] = low[v] = ++flag; 29 instack[v] = 1; 30 s[top++] = v; 31 for (int i = head[v] ; i != -1 ; i = edge[i].next) { 32 int j = edge[i].v; 33 if (!dfn[j]) { 34 tarjin(j); 35 low[v] = min(low[v], low[j]); 36 } else if (instack[j]) low[v] = min(low[v], dfn[j]); 37 } 38 if (dfn[v] == low[v]) { 39 cnt++; 40 int t; 41 do { 42 t = s[--top]; 43 instack[t] = 0; 44 belong[t] = cnt; 45 } while(t != v) ; 46 } 47 } 48 void solve() { 49 for (int i = 1 ; i <= n ; i++) 50 if (!dfn[i]) tarjin(i); 51 } 52 int in[maxn], out[maxn]; 53 int main() { 54 while(scanf("%d", &n) != EOF) { 55 init(); 56 memset(in, 0, sizeof(in)); 57 memset(out, 0, sizeof(out)) ; 58 for (int i = 1 ; i <= n ; i++) { 59 int v; 60 scanf("%d", &v); 61 while(v) { 62 add(i, v); 63 scanf("%d", &v); 64 } 65 } 66 for (int i = 1 ; i <= n ; i++) 67 if (!dfn[i]) tarjin(i); 68 for (int i = 1 ; i <= n ; i++) { 69 for (int j = head[i] ; ~j ; j = edge[j].next) { 70 if (belong[edge[j].v] != belong[i]) { 71 in[belong[edge[j].v]]++; 72 out[belong[i]]++; 73 } 74 } 75 } 76 int sumin = 0, sumout = 0; 77 for (int i = 1 ; i <= cnt ; i++) { 78 if (!in[i]) sumin++; 79 if (!out[i])sumout++; 80 } 81 printf("%d\n", sumin); 82 if (cnt == 1) printf("0\n"); 83 else printf("%d\n", max(sumin, sumout)); 84 } 85 return 0; 86 }