标签:
Caocao‘s Bridges
Problem Description
Caocao was defeated by Zhuge Liang and Zhou Yu in the battle of Chibi. But he wouldn‘t give up. Caocao‘s army still was not good at water battles, so he came up with another idea. He built many islands in the Changjiang river, and based on those islands, Caocao‘s army could easily attack Zhou Yu‘s troop. Caocao also built bridges connecting islands. If all islands were connected by bridges, Caocao‘s army could be deployed very conveniently among those islands. Zhou Yu couldn‘t stand with that, so he wanted to destroy some Caocao‘s bridges so one or more islands would be seperated from other islands. But Zhou Yu had only one bomb which was left by Zhuge Liang, so he could only destroy one bridge. Zhou Yu must send someone carrying the bomb to destroy the bridge. There might be guards on bridges. The soldier number of the bombing team couldn‘t be less than the guard number of a bridge, or the mission would fail. Please figure out as least how many soldiers Zhou Yu have to sent to complete the island seperating mission.
Input
There are no more than 12 test cases.
In each test case:
The first line contains two integers, N and M, meaning that there are N islands and M bridges. All the islands are numbered from 1 to N. ( 2 <= N <= 1000, 0 < M <= N2 )
Next M lines describes M bridges. Each line contains three integers U,V and W, meaning that there is a bridge connecting island U and island V, and there are W guards on that bridge. ( U ≠ V and 0 <= W <= 10,000 )
The input ends with N = 0 and M = 0.
Output
For each test case, print the minimum soldier number Zhou Yu had to send to complete the mission. If Zhou Yu couldn‘t succeed any way, print -1 instead.
Sample Input
3 3
1 2 7
2 3 4
3 1 4
3 2
1 2 7
2 3 4
0 0
Sample Output
题意:
曹操在长江上建立了一些点,点之间有一些边连着。如果这些点构成的无向图变成了连通图,那么曹操就无敌了。刘备为了防止曹操变得无敌,就打算去摧毁连接曹操的点的桥。但是诸葛亮把所有炸弹都带走了,只留下一枚给刘备。所以刘备只能炸一条桥。
题目给出n,m。表示有n个点,m条桥。
接下来的m行每行给出a,b,c,表示a点和b点之间有一条桥,而且曹操派了c个人去守卫这条桥。
现在问刘备最少派多少人去炸桥。
如果无法使曹操的点成为多个连通图,则输出-1.
题解:
集百家之长hhhh
1.图是边双连通图,就做不到删除一边得到两个连通块,这种情况输出-1.
2.图是连通但不边双联通,就用tarjan找出桥中权值最小的,这里有个巨坑,如果桥最小的权值为0,这时根据题意,要输出1而不是0(看看题就能理解)。
3.图不是连通的,就不需要去删边,即直接输出0。
在边(u,v)中,若low[v]>dfn[u],则(u,v)为割边,但是实际处理时我们并不这样判断,因为有的图上可能有重边,这样不好处理。我们记录每条边的标号(一条无向边拆成的两条有向边标号相同),记录每个点的父亲到它的边的标号,如果边(u,v)是v的父亲边,就不能用dfn[u]更新low[v]。这样如果遍历完v的所有子节点后,发现dfn[u]<low[v],说明边(u,v)为割边。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
#include<string>
#include<map>
#include<cmath>
#define clr(a,b) memset((a),b,sizeof((a)))
#define PB(x) push_back(x)
#define INF 0xfffffff
using namespace std;
const int maxn=1010;
const int maxm=maxn*maxn*2;
int dfn[maxn],low[maxn],head[maxn];
int num,tot;
int ans;
struct node{
int v,c,next,id;
}e[maxm];
int n,m;
void tarjan(int u,int fa){
dfn[u]=low[u]=++num;
for(int i=head[u];~i;i=e[i].next){
int v=e[i].v;
int id=e[i].id;
if(fa==id) continue;
if(!dfn[v]){
tarjan(v,id);
low[u]=min(low[u],low[v]);
if(dfn[u]<low[v]){
ans=min(ans,e[i].c);
}
}
else{
low[u]=min(low[u],dfn[v]);
}
}
}
void add(int u,int v,int c,int id){
e[tot].c=c;
e[tot].v=v;
e[tot].id=id;
e[tot].next=head[u];
head[u]=tot++;
}
int main()
{
while(cin>>n>>m,n||m){
int u,v,c;
tot=0;
memset(head,-1,sizeof(head));
for(int i=1;i<=m;++i){
scanf("%d%d%d",&u,&v,&c);
add(u,v,c,i);
add(v,u,c,i);
}
memset(dfn,0,sizeof(dfn));
num=0;
int ok=0;
ans=INF;
for(int i=1;i<=n;++i)
if(!dfn[i]){
ok++;
tarjan(i,0);
}
if(ans==0) ans=1;
if(ans==INF) ans=-1;
if(ok>1) ans=0;
// for(int i=1;i<=n;++i) cout<<dfn[i]<<" "<<low[i]<<endl;
cout<<ans<<endl;
}
return 0;
}
Recommend
HDU 4738 Caocao's Bridges tarjan求桥
标签:
原文地址:http://www.cnblogs.com/zxhl/p/5380253.html