题目链接

题意:

给出 n 个点 m 条边的无向图,输出权值最小的桥

题解:

桥模板题

如果无向图本身就已经是不连通的了,直接输出 0 即可 (用并查集判断一下)

因为存在权值为 0 的情况,因此如果求出来的最小权值桥的权值为 0 时,根据题意,输出 1。

注意处理重边

代码:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include<vector>
#include <map>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn = 1e4+5;//点数
const int maxm = 2e6+5;//边数,因为是无向图,所以这个值要*2

struct Edge
{
    int to,next;
    int w;
    bool cut;//是否是桥标记
} edge[maxm];
int head[maxn],tot;
int low[maxn],dfn[maxn],Stack[maxn],belong[maxn];//belong数组的值是1~scc
int Index,top;
int scc;//边双连通块数/强连通分量的个数
bool Instack[maxn];
int bridge;//桥的数目
int cut[maxn];
int num[maxn];
void addedge(int u,int v,int w)
{
    edge[tot].to = v;
    edge[tot].next = head[u];
    edge[tot].cut=false;
    edge[tot].w=w;
    head[u] = tot++;
}

void Tarjan(int u,int pre)
{
    int v;
    low[u] = dfn[u] = ++Index;
    Stack[top++] = u;
    Instack[u] = true;
    int son=0;
    int flag=0;
    for(int i = head[u]; i != -1; i = edge[i].next)
    {
        v = edge[i].to;
        if(v == pre && !flag)
        {
            flag++;
            continue;
        }

        if( !dfn[v] )
        {
            son++;
            Tarjan(v,u);
            if( low[u] > low[v] )low[u] = low[v];

            if(low[v] > dfn[u])
            {
                bridge++;
                edge[i].cut = true;
                edge[i^1].cut = true;
            }

            if(u == pre && son > 1)cut[u] = true;
            if(u != pre && low[v] >= dfn[u])cut[u] = true;

        }
        else if( Instack[v] && low[u] > dfn[v] )
            low[u] = dfn[v];
    }

    if(low[u] == dfn[u])
    {
        scc++;
        do
        {
            v = Stack[--top];
            Instack[v] = false;
            belong[v] = scc;
            num[scc]++;

        }
        while( v!=u );
    }

}

void init()
{
    tot = 0;
    memset(head,-1,sizeof(head));
}
int solve(int n)
{
    memset(dfn,0,sizeof(dfn));
    memset(Instack,false,sizeof(Instack));
    memset(cut,0,sizeof cut);
    memset(num,0,sizeof num);
    Index = top = scc = 0;
    bridge = 0;
    for(int i = 1; i <= n; i++)
        if(!dfn[i])
            Tarjan(i,i);
    int res=inf;
    for(int u=1;u<=n;u++)
    {
        for(int i=head[u];~i;i=edge[i].next)
            if(edge[i].cut)res=min(res,edge[i].w);
    }
    if(res==inf)return -1;
    if(res==0)return 1;
    return res;

}
int pre[maxn];
int Find(int x)
{
    return x==pre[x]?x:pre[x]=Find(pre[x]);
}
int join(int x,int y)
{
    int fx=Find(x);
    int fy=Find(y);
    if(fx!=fy)pre[fx]=fy;
}
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m) && (n&&m))
    {
        init();
        for(int i=1; i<=n; i++)pre[i]=i;
        for(int i=1; i<=m; i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w);
            addedge(v,u,w);
            join(u,v);
        }

        int flag=0;
        for(int i=1; i<=n; i++)
            if(Find(i)!=Find(1))flag=1;
        if(flag)printf("0\n");
        else
        {
            printf("%d\n",solve(n));
        }

    }
    return 0;
}
/*
5
2 4 3 0
4 5 0
0
0
1 0
*/
View Code
02-13 12:57