题目描述:
在赤壁之战中,曹操被诸葛亮和周瑜击败。但他不会放弃。曹操的军队仍然不善于水战,所以他提出了另一个想法。他在长江建造了许多岛屿,在这些岛屿的基础上,曹操的军队很容易攻击周瑜的部队。曹操还建造了连接岛屿的桥梁。如果所有岛屿都通过桥梁相连,那么曹操的军队可以在这些岛屿中非常方便地部署。周瑜无法忍受,所以他想要摧毁一些曹操的桥梁,这样一个或多个岛屿就会与其他岛屿分开。但周瑜只有一枚由诸葛亮留下的炸弹,所以他只能摧毁一座桥。周瑜必须派人携带炸弹来摧毁这座桥。桥上可能有守卫。轰炸队的士兵数量不能低于桥梁的守卫数量,否则任务就会失败。请弄清楚周瑜至少需要多少士兵。
输入:
测试用例不超过12个。
在每个测试用例中:
第一行包含两个整数N和M,意味着有N个岛和M个桥。所有岛都从1到N编号。(2 <= N <= 1000,0 <M <= N²)
接下来的M行描述了M个桥。每条线包含三个整数U,V和W,意味着有一个连接岛U和岛V的桥,并且在该桥上有W守卫。(U≠V且0 <= W <= 10,000)
输入以N = 0且M = 0结束。
输出:
对于每个测试用例,输出周瑜完成任务所需的最少士兵数量。如果周瑜无法成功,请输出-1。
输入样例:
3 3
1 2 7
2 3 4
3 1 4
3 2
1 2 7
2 3 4
0 0
输出样例:
-1
4
思路分析:
其实这一题就是用Tanjar求割边,然后找花费的最小值的边。
主要是这几个特判情况。
假设图本身就不联通,那么就不要人。
如果没有割边,那么就没有答案。
最后一个就是割边的守卫为0,但是也要一人去炸。
代码实现:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
int n,m,low[1005],dfn[1005],cnt,a[1000005],p,ans;
bool iscut[1000005];
struct node{
int to,nu,w;
node(int To,int Nu,int W)
{
to=To;
nu=Nu;
w=W;
}
};
vector<node>G[1005];
void Tarjan(int u,int fanu)
{
cnt++;
low[u]=cnt;
dfn[u]=cnt;
int child=0;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i].to;
int vnu=G[u][i].nu;
if(!dfn[v])
{
child++;
Tarjan(v,vnu);
if(low[v]>dfn[u])
{
iscut[vnu]=1;
ans=min(ans,G[u][i].w);
}
low[u]=min(low[u],low[v]);
}
else if(dfn[u]>dfn[v]&&vnu!=fanu)
low[u]=min(dfn[v],low[u]);
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=-1&&n)
{
p=0;
ans=0x3f3f3f3f;
cnt=0;
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
memset(a,0,sizeof(a));
memset(iscut,0,sizeof(iscut));
int a1,b,c;
for(int i=1;i<=n;i++)
G[i].clear();
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a1,&b,&c);
G[a1].push_back(node(b,i,c));
G[b].push_back(node(a1,i,c));
}
for(int i=1;i<=n;i++)
{
if(!dfn[i])
{
p++;
Tarjan(i,-1);
}
}
if(p>1)
{
printf("0\n");
continue;
}
if(ans==1061109567)
printf("-1\n");
else
printf("%d\n",max(1,ans));
}
}