题意:曹操把几个小岛用桥连了起来。每个桥有一定量的士兵守着。周瑜要炸一个桥,使这几个小岛不连同。派出的最少的士兵的数量是守卫要炸的桥的士兵的数量。问最少要派多少士兵。
思路:求一个图中的桥。注意如果图本身不连通,就不需要派人去。如果要炸的桥没人看守,至少要派一个人去。题目给出的图可能有重边。在重边上死了好多次。。。
代码如下:
#include <cstring>
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <map>
#include <string>
#include <queue>
#include <bitset>
using namespace std;
const int maxn=1005;
struct Edge{
int u,v,next;
int w;
}edge[maxn*maxn];
int first[maxn];
int tot;
void add(int uu,int vv,int ww)
{
edge[tot].u=uu;
edge[tot].v=vv;
edge[tot].w=ww;
edge[tot].next = first[uu];
first[uu]=tot++;
}
vector<int> cost;
int low[maxn],dfn[maxn],vis[maxn];
void cut_bridge(int cur, int father, int dep,int n)
{
vis[cur]=1; dfn[cur] =low[cur] = dep;
for(int i=first[cur];i!=-1;i=edge[i].next){
int v=edge[i].v;
if( i!=(father^1) && 1 == vis[v]){
if(dfn[v]<low[cur]){
low[cur] = dfn[v];
}
}
if(0==vis[v]){
cut_bridge(v,i,dep+1,n);
if(low[v]<low[cur])low[cur]=low[v];
if(low[v]>dfn[cur])cost.push_back(edge[i].w);
}
}
vis[cur]=2;
}
bool check(int n)
{
for(int i=1;i<=n;++i){
if(vis[i]==0)return true;
}
return false;
}
int main()
{
// freopen("data.txt","r",stdin);
int n,m;
while(scanf("%d%d",&n,&m)!=EOF&&n&&m){
tot=0;
memset(first,-1,sizeof(first));
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
for(int i=0;i<m;++i){
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
add(u,v,c);
add(v,u,c);
}
cost.clear();
memset(vis,0,sizeof(vis));
cut_bridge(1,-1,0,n);
if(check(n)){
puts("0");
continue;
}
if(cost.empty()){
puts("-1");
continue;
}
sort(cost.begin(),cost.end());
printf("%d\n",max(cost[0],1));
}
return 0;
}