/*****
证明:
割边:本来连通图,去掉该边之后,原图不连通,次边称为割边
如何求割边呢?
首先如果u->v是割边那么v的子孙节点没有边连接到v的祖先,那么
这条边就是割边
*********/
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
struct
{
int head;
}H[20000];
int low[20000],dfs[20000];
struct
{
int u,v,next,w;
}E[2000000];
int top = 0,ans,c_cont,index;
void add(int u,int v,int w)
{
E[top].v = v;
E[top].w = w;
E[top].next = H[u].head;
H[u].head = top++;
}
const int inf = 0x7777777;
void initside()
{
memset(H,-1,sizeof(H));
memset(E,-1,sizeof(E));
memset(dfs,0,sizeof(dfs));
memset(low,0,sizeof(low));
index = top = 0;
ans = inf;
c_cont = 0;
}
int sn;
void tarjan(int u,int fa)
{
dfs[u] = low[u] = ++index;
for(int i=H[u].head;i!=-1;i=E[i].next)
{
int v = E[i].v;
if(i == (fa^1))continue; // 防止从v再到u
if(!dfs[v])
{
// cout<<v<<endl;
tarjan(v,i);
low[u] = min(low[u],low[v]);
if(low[v]>dfs[u]) // 此边为割边
{
// cout<<v<<"-->"<<u<<" "<<i<<endl;
sn++;
ans = min(ans,E[i].w);
}
}
else
low[u] = min(low[u],dfs[v]);// 如果找到了v是以前曾经访问过,那么把此时的low[u]更新成low[v]
}
c_cont++;
}
int main()
{
int n,m;
int u,v,w;
while(~scanf("%d%d",&n,&m),n||m)
{
initside();
sn = 0;
while(m--)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
tarjan(1,-1);
if(c_cont<n) puts("0");
else if(ans == 0)puts("1");
else if(sn == 0)puts("-1");
else printf("%d\n",ans);
}
}
hdu 4738 图的割边
最新推荐文章于 2021-04-18 18:13:29 发布