題目描述:
在赤壁之戰中,曹操被諸葛亮和周瑜擊敗。但他不會放棄。曹操的軍隊仍然不善於水戰,所以他提出了另一個想法。他在長江建造了許多島嶼,在這些島嶼的基礎上,曹操的軍隊很容易攻擊周瑜的部隊。曹操還建造了連接島嶼的橋樑。如果所有島嶼都通過橋樑相連,那麼曹操的軍隊可以在這些島嶼中非常方便地部署。周瑜無法忍受,所以他想要摧毀一些曹操的橋樑,這樣一個或多個島嶼就會與其他島嶼分開。但周瑜只有一枚由諸葛亮留下的炸彈,所以他只能摧毀一座橋。周瑜必須派人攜帶炸彈來摧毀這座橋。橋上可能有守衛。轟炸隊的士兵數量不能低於橋樑的守衛數量,否則任務就會失敗。請弄清楚周瑜至少需要多少士兵。
輸入:
測試用例不超過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));
}
}