題目連接:https://vjudge.net/problem/POJ-1236node
題目:有向圖,有若干個連通圖,點之間有單向邊邊就能夠單向傳遞信息,問:ios
(1)至少須要發送幾份信息才能使得每一個點都傳遞到信息ui
(2)至少須要加幾條邊,才能使得「把一份信息發送到任意某個點就能傳播到其餘全部點」成立spa
思路:tarjan求強連通份量,強聯通份量能夠相互傳遞消息,而後,按強聯通編號重構圖,.net
統計每一個強聯通份量的入度出度狀況。第一個答案,就顯然是入度爲0的點,第二個就是max(p,q),構成一個強聯通圖code
這裏給狀況來解釋下max (1)1->2 3->2 (2) 1->2 1->3blog
p = 入度爲0的強聯通份量數get
q = 出爲爲0的強聯通份量數it
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 6 const int N = 110; 7 int head[N],dfn[N],low[N],scc_no[N],s[N],ins[N],ru[N],chu[N]; 8 int n,scc,tim,tot,top; 9 struct node{ 10 int to; 11 int nxt; 12 }e[N*N]; 13 14 inline void add(int u,int v){ 15 e[tot].to = v; 16 e[tot].nxt = head[u]; 17 head[u] = tot++; 18 } 19 20 void tarjan(int now,int pre){ 21 dfn[now] = low[now] = ++tim; 22 ins[now] = 1; 23 s[top++] = now; 24 25 int to; 26 for(int o = head[now]; ~o; o = e[o].nxt){ 27 to = e[o].to; 28 if(!dfn[to]){ 29 tarjan(to,now); 30 low[now] = min(low[now],low[to]); 31 } 32 else if(ins[to] && low[now] > dfn[to]) low[now] = dfn[to]; 33 } 34 35 if(dfn[now] == low[now]){ 36 int x; 37 ++scc; 38 do{ 39 x= s[--top]; 40 ins[x] = 0; 41 scc_no[x] = scc; 42 }while(now != x); 43 } 44 } 45 46 //重構圖,統計入度出度狀況 47 void rebuild(){ 48 int to; 49 for(int now = 1; now <= n; ++now){ 50 for(int o = head[now]; ~o; o = e[o].nxt){ 51 to = e[o].to; 52 if(scc_no[to] != scc_no[now]){ 53 ++ru[scc_no[to]]; 54 ++chu[scc_no[now]]; 55 } 56 } 57 } 58 } 59 60 int main(){ 61 62 scanf("%d",&n); 63 for(int i = 0; i <= n; ++i) head[i] = -1; 64 int v; 65 for(int u = 1; u <= n; ++u){ 66 while(~scanf("%d",&v) && v){ 67 add(u,v); 68 } 69 } 70 for(int i = 1; i <= n; ++i){ 71 if(!dfn[i]) 72 tarjan(i,i); 73 } 74 rebuild(); 75 int p = 0,q = 0; 76 for(int i = 1; i <= scc; ++i){ 77 if(!ru[i]) ++p; 78 if(!chu[i]) ++q; 79 } 80 if(scc == 1) printf("1\n0\n"); 81 else printf("%d\n%d\n",p,max(p,q)); 82 83 84 return 0; 85 }