1. 程式人生 > >poj~1236 Network of Schools 強連通入門題

poj~1236 Network of Schools 強連通入門題

str max 計算 () printf bsp 我們 jin ++

一些學校連接到計算機網絡。這些學校之間已經達成了協議:

每所學校都有一份分發軟件的學校名單(“接收學校”)。

請註意,如果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 }

poj~1236 Network of Schools 強連通入門題