双联通分量 HDU4738

题意:给你一张图,求w最小的桥。
http://acm.hdu.edu.cn/showproblem.php?pid=4738

注意:可能不是联通图(先用并查集判断联通),没有人的时候要输出1,没有桥输出-1。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define MAXN 100010
#define MAXM 2000010
using namespace std;
struct Edge
{
    int to,next;
    int w;
    bool cut;
}edge[MAXM];
int n,m;
int head[MAXN],top;
int LOW[MAXN],DFN[MAXN],Index;
int f[MAXN];
void add(int u,int v,int w)
{
    edge[top].to=v;
    edge[top].next=head[u];
    edge[top].cut=false;
    edge[top].w=w;
    head[u]=top++;
}
void init()
{
    Index=0;
    memset(head,-1,sizeof(head));
    memset(DFN,0,sizeof(DFN));
    for(int i=1;i<=n;i++)
        f[i]=i;
    top=0;
}
void Tarjan(int u,int fa)
{
    DFN[u]=LOW[u]=++Index;
    int f=1;
    for(int i = head[u];i != -1;i = edge[i].next)
    {
        int v=edge[i].to;
        if(v==fa&&f)
        {
            f=0;
            continue;
        }
        if(!DFN[v])
        {
            Tarjan(v,u);
            LOW[u]=min(LOW[u],LOW[v]);
            if(LOW[v]>DFN[u])
            {
                edge[i].cut=true;
            }
        }
        else if(DFN[v]<DFN[u])
            LOW[u]=min(LOW[u],DFN[v]);
    }
}
int find(int x)
{
    if(f[x]!=x)f[x]=find(f[x]);
    return f[x];
}
void Union(int a,int b)
{
    int a1=find(a);
    int b1=find(b);
    if(a1!=b1)
    {
        f[a1]=b1;
    }
}
void solve()
{
    for(int i=1;i<=n;i++)
        if(!DFN[i])
            Tarjan(i,i);
    int ans=999999999;
    for(int u=1;u<=n;u++)
    {
        for(int i=head[u];i!=-1;i=edge[i].next)
            if(edge[i].cut)
                ans=min(ans,edge[i].w);
    }
    if(ans==999999999)cout<<-1<<endl;
    else if(ans==0)cout<<1<<endl;
    else cout<<ans<<endl;
}
int main()
{
    while(cin>>n>>m&&(n||m))
    {
        init();
        for(int i=0;i<m;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            if(u==v)continue ;
            add(u,v,w);
            add(v,u,w);
            Union(u,v);
        }
        bool flag=1;
        for(int i=1;i<=n;i++)
        {
            if(find(i)!=find(1))
                flag=0;
        }
        if(flag==0)
            cout<<0<<endl;
        else
            solve();

    }
}

猜你喜欢

转载自blog.csdn.net/prometheus_97/article/details/78534430