Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 194 Accepted Submission(s): 89
这题的意思就是求出所有的桥,然后输出桥的权值的最小值。
但是坑点比较多。
如果一开始是不连通的,输出0.
图有重边,需要处理。
还有如果取到的最小值是0的话,要输出1,表示要派一个人过去。
1 /* *********************************************** 2 Author :kuangbin 3 Created Time :2013/9/15 星期日 12:11:49 4 File Name :2013杭州网络赛\1001.cpp 5 ************************************************ */ 6 7 #pragma comment(linker, "/STACK:1024000000,1024000000") 8 #include <stdio.h> 9 #include <string.h> 10 #include <iostream> 11 #include <algorithm> 12 #include <vector> 13 #include <queue> 14 #include <set> 15 #include <map> 16 #include <string> 17 #include <math.h> 18 #include <stdlib.h> 19 #include <time.h> 20 using namespace std; 21 const int INF = 0x3f3f3f3f; 22 /* 23 * 求 无向图的割点和桥 24 * 可以找出割点和桥,求删掉每个点后增加的连通块。 25 * 需要注意重边的处理,可以先用矩阵存,再转邻接表,或者进行判重 26 */ 27 const int MAXN = 10010; 28 const int MAXM = 2000010; 29 struct Edge 30 { 31 int to,next; 32 int w; 33 bool cut;//是否为桥的标记 34 }edge[MAXM]; 35 int head[MAXN],tot; 36 int Low[MAXN],DFN[MAXN],Stack[MAXN]; 37 int Index,top; 38 bool Instack[MAXN]; 39 bool cut[MAXN]; 40 int add_block[MAXN];//删除一个点后增加的连通块 41 int bridge; 42 43 void addedge(int u,int v,int w) 44 { 45 edge[tot].to = v;edge[tot].next = head[u];edge[tot].cut = false; 46 edge[tot].w = w; 47 head[u] = tot++; 48 } 49 50 51 void Tarjan(int u,int pre) 52 { 53 int v; 54 Low[u] = DFN[u] = ++Index; 55 Stack[top++] = u; 56 Instack[u] = true; 57 int son = 0; 58 int pre_num = 0; 59 for(int i = head[u];i != -1;i = edge[i].next) 60 { 61 v = edge[i].to; 62 if(v == pre && pre_num == 0) 63 { 64 pre_num++; 65 continue; 66 67 } 68 if( !DFN[v] ) 69 { 70 son++; 71 Tarjan(v,u); 72 if(Low[u] > Low[v])Low[u] = Low[v]; 73 //桥 74 //一条无向边(u,v)是桥,当且仅当(u,v)为树枝边,且满足DFS(u)<Low(v)。 75 if(Low[v] > DFN[u]) 76 { 77 bridge++; 78 edge[i].cut = true; 79 edge[i^1].cut = true; 80 } 81 //割点 82 //一个顶点u是割点,当且仅当满足(1)或(2) (1) u为树根,且u有多于一个子树。 83 //(2) u不为树根,且满足存在(u,v)为树枝边(或称父子边, 84 //即u为v在搜索树中的父亲),使得DFS(u)<=Low(v) 85 if(u != pre && Low[v] >= DFN[u])//不是树根 86 { 87 cut[u] = true; 88 add_block[u]++; 89 } 90 } 91 else if( Low[u] > DFN[v]) 92 Low[u] = DFN[v]; 93 } 94 //树根,分支数大于1 95 if(u == pre && son > 1)cut[u] = true; 96 if(u == pre)add_block[u] = son - 1; 97 Instack[u] = false; 98 top--; 99 } 100 int solve(int N) 101 { 102 memset(DFN,0,sizeof(DFN)); 103 memset(Instack,false,sizeof(Instack)); 104 memset(add_block,0,sizeof(add_block)); 105 memset(cut,false,sizeof(cut)); 106 Index = top = 0; 107 bridge = 0; 108 for(int i = 1;i <= N;i++) 109 if( !DFN[i] ) 110 Tarjan(i,i); 111 int ret = INF; 112 for(int u = 1; u <= N;u++) 113 for(int i = head[u]; i != -1;i = edge[i].next) 114 if(edge[i].cut) 115 ret = min(ret,edge[i].w); 116 if(ret == INF)ret = -1; 117 if(ret == 0)ret++; 118 return ret; 119 } 120 int F[MAXN]; 121 int find(int x) 122 { 123 if(F[x] == -1)return x; 124 else return F[x] = find(F[x]); 125 } 126 void init() 127 { 128 memset(F,-1,sizeof(F)); 129 tot = 0; 130 memset(head,-1,sizeof(head)); 131 } 132 void bing(int u,int v) 133 { 134 int t1 = find(u); 135 int t2 = find(v); 136 if(t1 != t2)F[t1] = t2; 137 } 138 int main() 139 { 140 //freopen("in.txt","r",stdin); 141 //freopen("out.txt","w",stdout); 142 int n,m; 143 while(scanf("%d%d",&n,&m) == 2) 144 { 145 if(n == 0 && m == 0)break; 146 int u,v,w; 147 init(); 148 while(m--) 149 { 150 scanf("%d%d%d",&u,&v,&w); 151 if(u == v)continue; 152 addedge(u,v,w); 153 addedge(v,u,w); 154 bing(u,v); 155 } 156 bool flag = true; 157 for(int i = 1; i <= n;i++) 158 if(find(i) != find(1)) 159 flag = false; 160 if(!flag) 161 { 162 printf("0\n"); 163 continue; 164 } 165 printf("%d\n",solve(n)); 166 } 167 return 0; 168 }