題目連接:http://poj.org/problem?id=1236
題目大意:給出N臺電腦,電腦間單向連通傳送文件
問題1.網絡中最少放幾個文件保證全部電腦都能接受到文件
問題2.最少向網絡中加幾條線保證任意放1個文件全部電腦都能接受到
解題思路:
1.求出強連通份量
2.縮點 ,進行從新構圖
3.若是入度爲0,說明沒有文件傳輸到該網絡。解決問題1,統計入度爲0的個數便可
4.一個強連通圖的入度和出度都不爲0。入度爲0至關於根root,出度爲0至關於葉子leave.max(root, leave)即爲答案。
就是須要加的線數,保證整個網絡強連通。
若連通份量個數爲0,那麼答案爲0node
代碼以下:ios
#include<stdio.h> #include<string.h> #include<iostream> using namespace std; #define N 105 #define M 10005 struct Edge { int v, next; }edge[M]; int node[N], stack[N], instack[N], dfn[N], out[N], in[N]; int low[N], belong[N], index, cnt_edge, n, m, cnt_tar, top; int ee[M][2]; void add_Edge(int u, int v) { edge[cnt_edge].next=node[u]; edge[cnt_edge].v=v; node[u]=cnt_edge++; } void tarjan(int u) { int i, j, v; dfn[u]=low[u]=++index; stack[++top]=u; instack[u]=1; for(i=node[u]; i!=-1; i=edge[i].next) { v=edge[i].v; if(!dfn[v]) { tarjan(v); low[u]=min(low[u], low[v]); } else if(instack[v]) low[u]=min(low[u], dfn[v]); } if(dfn[u]==low[u]) { cnt_tar++; do { j=stack[top--]; instack[j]=0; belong[j]=cnt_tar; }while(j!=u); } } void solve() { int i; top=0, index=0, cnt_tar=0; memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); for(i=1; i<=n; i++) if(!dfn[i]) tarjan(i); } int main() { int i, u, v; while(scanf("%d", &n)!=EOF) { cnt_edge=0, m=1; memset(node, -1, sizeof(node)); memset(in, 0, sizeof(in)); memset(out, 0, sizeof(out)); for(i=1; i<=n; i++) { while(scanf("%d", &v)) { if(v==0) break; ee[m][0]=i, ee[m++][1]=v; add_Edge(i, v); } } solve(); for(i=1; i<=m; i++) { int xx=belong[ee[i][0]], yy=belong[ee[i][1]]; if(xx!=yy) { in[yy]++; out[xx]++; } } int innum=0, outnum=0; for(i=1; i<=cnt_tar; i++) { if(in[i]==0) innum++; if(out[i]==0) outnum++; } if(cnt_tar==1) printf("1\n0\n"); else printf("%d\n%d\n", innum, max(innum, outnum)); } return 0; }