题目大意:
给出一幅图,然后每条边上都有一个权值,权值代表需要多少兵才可以炸断桥,求用最少的兵力使连通图变得不连通。
题目思路:
其实这题。。很简单,就是有两个坑。
(1)就是某个边权值为0的时候是要派出1个兵去炸的
(2)他会给出不连通的图,所以当Tarjan进行了两次以上的时候便输出0
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 3000
#define INF 0x7FFFFFF
struct node
{
int u;
int v;
int next;
int w;
}edge[N*N];
int head[N];
int cnt;
void add(int u,int v,int w)
{
edge[cnt].u = u;
edge[cnt].v = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt ++ ;
}
int dfn[N],low[N],fa[N],nTime;
int stack[N],ins[N],num,top;
int n,m;
inline int min(int a,int b)
{
return a<b?a:b;
}
void init()
{
cnt = num = nTime = top = 0;
memset(head,-1,sizeof(head));
memset(fa,-1,sizeof(fa));
memset(ins,0,sizeof(ins));
memset(dfn,-1,sizeof(dfn));
}
void Tarjan(int u,int pre)
{
int i,walk = 1;
dfn[u] = low[u] = ++nTime;
ins[u] = 1;
stack[top++] = u;
for(i = head[u] ; i!=-1 ; i = edge[i].next )
{
int v = edge[i].v;
if( v==pre && walk )
{
walk = 0;
continue;
}
if(dfn[v] == -1)
{
Tarjan(v,u);
low[u] = min(low[u],low[v]);
}
else if( ins[v] )
low[u] = min(low[u],dfn[v]);
}
if( low[u] == dfn[u] )
{
int v;
num ++;
do
{
v = stack[--top];
fa[v] = num;
ins[v] = 0;
}while(u!=v);
}
}
int solve()
{
init();
int i,u,v,w;
for(i=0 ;i < m;i ++ )
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
int you= 0;
for(i = 1; i <= n; i ++ )
{
if( dfn[i] == -1 )
{
Tarjan(i,-1);
you++;
}
}
if(you>1)
return 0;
int ans = INF;
for(i=0;i<cnt;i++)
{
u = fa[edge[i].u];
v = fa[edge[i].v];
if(u!=v)
ans = min(ans,edge[i].w);
}
if(ans>=INF)
return -1;
else if(ans == 0 )
return 1;
else
return ans;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
if(!n && !m)
break;
printf("%d\n",solve());
}
return 0;
}