1 2 5 4 3 1 3 2 3 4 3 5 0 1 2 2 3 3 4 4 5 5 1 0 1 2 2 3 3 4 4 6 6 3 2 5 5 1 0 0
Network #1 SPF node 3 leaves 2 subnets Network #2 No SPF nodes Network #3 SPF node 2 leaves 2 subnets SPF node 3 leaves 2 subnets
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <climits> 7 #include <vector> 8 #include <queue> 9 #include <cstdlib> 10 #include <string> 11 #include <set> 12 #include <stack> 13 #define LL long long 14 #define pii pair<int,int> 15 #define INF 0x3f3f3f3f 16 using namespace std; 17 const int maxn = 1010; 18 vector<int>g[maxn]; 19 bool iscut[maxn]; 20 int dfn[maxn],low[maxn],cnt,vis[maxn]; 21 void tarjan(int u,int fa) { 22 dfn[u] = low[u] = ++cnt; 23 vis[u] = 1; 24 int son = 0; 25 for(int i = 0; i < g[u].size(); i++) { 26 if(!vis[g[u][i]]) { 27 tarjan(g[u][i],u); 28 son++; 29 low[u] = min(low[u],low[g[u][i]]); 30 if(fa == -1 && son > 1 || fa != -1 && low[g[u][i]] >= dfn[u]) 31 iscut[u] = true; 32 } else if(vis[g[u][i]] == 1) low[u] = min(low[u],dfn[g[u][i]]); 33 } 34 vis[u] = 2; 35 } 36 void dfs(int u) { 37 vis[u] = 1; 38 for(int i = 0; i < g[u].size(); i++) 39 if(!vis[g[u][i]]) dfs(g[u][i]); 40 } 41 void init() { 42 memset(vis,0,sizeof(vis)); 43 memset(iscut,false,sizeof(iscut)); 44 for(int i = 0; i < maxn; i++) g[i].clear(); 45 } 46 int main() { 47 int i,j,u,v,ks = 1,n,son; 48 bool flag; 49 while(scanf("%d",&u),u) { 50 n = 0; 51 init(); 52 scanf("%d",&v); 53 n = max(max(u,v),n); 54 g[u].push_back(v); 55 g[v].push_back(u); 56 while(scanf("%d",&u),u) { 57 scanf("%d",&v); 58 n = max(max(u,v),n); 59 g[u].push_back(v); 60 g[v].push_back(u); 61 } 62 flag = true; 63 tarjan(1,-1); 64 printf("Network #%d\n",ks++); 65 for(i = 1; i <= n; i++) { 66 if(iscut[i]) { 67 flag = false; 68 son = 0; 69 memset(vis,0,sizeof(vis)); 70 vis[i] = 1;//记得把路锁死 71 for(j = 0; j < g[i].size(); j++) { 72 if(!vis[g[i][j]]) { 73 son++; 74 dfs(g[i][j]); 75 } 76 } 77 printf(" SPF node %d leaves %d subnets\n",i,son); 78 } 79 } 80 if(flag) puts(" No SPF nodes"); 81 puts(""); 82 } 83 return 0; 84 }
不用再次dfs的方案:
去掉该关节点u,将原来的连通图分成几个连通分量?答案如下:
(1)如果关节点u是根结点,则有几个子女,就分成几个连通分量。
(2)如果关节点u不是根节点,则有n个子女w,使得low[w]>= dfn[u],则去掉该点,分成了n+1个连通分量。
注意:第二条的儿子数不同于第一个条件的儿子数。。。第二个多了个约束
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 const int maxn = 1010; 7 struct arc { 8 int to,next; 9 arc(int x = 0,int y = -1) { 10 to = x; 11 next = y; 12 } 13 }; 14 arc e[maxn*100]; 15 int head[maxn],dfn[maxn],low[maxn],cut[maxn],tot,scc,idx; 16 void add(int u,int v) { 17 e[tot] = arc(v,head[u]); 18 head[u] = tot++; 19 } 20 void tarjan(int u,int fa) { 21 dfn[u] = low[u] = idx++; 22 int son = 0,gson = 0; 23 bool flag = true,iscut = false; 24 for(int i = head[u]; ~i; i = e[i].next) { 25 if(flag && e[i].to == fa) { 26 flag = false; 27 continue; 28 } 29 if(dfn[e[i].to] == -1) { 30 tarjan(e[i].to,u); 31 son++; 32 low[u] = min(low[u],low[e[i].to]); 33 if(fa == -1 && son >= 2) iscut = true; 34 if(fa != -1 && low[e[i].to]>= dfn[u]) iscut = true,gson++; 35 } else if(e[i].to != fa) low[u] = min(low[u],dfn[e[i].to]); 36 } 37 if(iscut && fa == -1) cut[u] = son-1; 38 else if(iscut && fa != -1) cut[u] = gson; 39 } 40 int main() { 41 int u,v,kase = 1; 42 while(scanf("%d",&u),u) { 43 scanf("%d",&v); 44 memset(head,-1,sizeof(head)); 45 memset(cut,0,sizeof(cut)); 46 memset(dfn,-1,sizeof(dfn)); 47 memset(low,-1,sizeof(low)); 48 idx = tot = 0; 49 add(u,v); 50 add(v,u); 51 int up = max(u,v); 52 while(scanf("%d",&u),u) { 53 scanf("%d",&v); 54 add(u,v); 55 add(v,u); 56 up = max(up,max(u,v)); 57 } 58 for(int i = 1; i <= up; ++i) 59 if(dfn[i] == -1) tarjan(i,-1); 60 int ans = 0; 61 printf("Network #%d\n",kase++); 62 for(int i = 1; i <= up; ++i) { 63 if(cut[i]) { 64 printf(" SPF node %d leaves %d subnets\n",i,cut[i]+1); 65 ans++; 66 } 67 } 68 if(!ans) puts(" No SPF nodes"); 69 puts(""); 70 } 71 return 0; 72 }