题目链接2013 ACM/ICPC Asia Regional Hangzhou Online
题意挺有意思的。曹操的军队在若干个岛屿之间修了桥,使得U–V联通,周瑜现在要去炸一座桥,使得其余岛屿不再能任意相互到达。爆破小队的人数必须大于等于该桥的守卫人数才能完成任务。现在请输出周瑜最少要派多少人或者输出-1 说明无法实现炸桥以后,破坏连通性。
问题分析:
显然这是一道求割边(桥)的题。Tarjan处理,注意重边,注意如果一开始就不连通,是不需要派人的,数量为0.但是如果存在桥且边权为0,就要派1人。其余情况自然洒洒水啦。
#include<bits/stdc++.h>
#include<algorithm>
#include<cstring>
#include<cstdio>
#define Re int
using namespace std;
const int N=3e4+3,M=1e6+200;
int n,m,x,y,ans,w,sc;
inline void in(Re &x){
int f=0;x=0;char c=getchar();
while(c<'0'||c>'9')f|=c=='-',c=getchar();
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=f?-x:x;
}
struct Tarjan{
int o,dfn_o,dfn[N],low[N],head[N],bridge[M<<1];
struct QAQ{int to,next,w;}a[M<<1];
inline void add(Re x,Re y,Re w){a[++o].to=y,a[o].w=w,a[o].next=head[x],head[x]=o;}
inline void CL(){
memset(bridge,0,sizeof(bridge));
memset(head,0,sizeof(head));
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
dfn_o=0,o=1;
ans=99999999;
sc=0;
}
inline void tarjan(Re x,Re p){
dfn[x]=low[x]=++dfn_o;
for(Re i=head[x],to;i;i=a[i].next)
if(!dfn[to=a[i].to]){
tarjan(to,i);
low[x]=min(low[x],low[to]);
if(low[to]>dfn[x])bridge[i]=bridge[i^1]=1,ans=min(ans,a[i].w);
}
else if(i!=(p^1))low[x]=min(low[x],dfn[to]);
}
inline void get_bridg(){for(Re i=1;i<=n;++i)if(!dfn[i])tarjan(i,-1),sc++;}
}T1;
int main(){
while(scanf("%d%d",&n,&m)!=EOF){
if(n<=0&&m<=0)break;
T1.CL();
// ans=1000000000;
while(m--)in(x),in(y),in(w),T1.add(x,y,w),T1.add(y,x,w);
T1.get_bridg();
if(sc>=2){
printf("0\n");
continue;
}
if(ans<99999999){
if(ans==0)ans++;
printf("%d\n",ans);
}
else printf("-1\n");
}
}