UVA-315 Network + UVA-796 Critical Links 无向连通图求割点与桥

这两道是板子题,我主要看的kuangbin的模板,因为割点与桥是连在一起求的,比较方便。网上也有很多其他的,但是没有找到合适的统一求割点与桥的模板。

附上大佬的博客Orz:

UVA-315:https://www.cnblogs.com/kuangbin/p/3184060.html

UVA-796:http://www.cnblogs.com/kuangbin/archive/2013/07/11/3184068.html

这个模板很全面了,但加边有讲究:正向边与反向边要同时加(相邻),可能因为有异或的操作。

附上一个混合了两道题的AC代码2333:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
typedef pair<int,int> pp;

const int MAXN = 10010;
const int MAXM = 100010;
struct Edge
{
    int to,next;
    bool iscut;//是否为桥
}edge[MAXM];
int head[MAXN],tot;
int low[MAXN],dfn[MAXN],st[MAXN];
int inde,top;
bool inst[MAXN];
bool iscut[MAXN];
int add_block[MAXN];//删除一个点后增加的连通块
int bridge;

void init()
{
    tot=0;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v)
{
    edge[tot].to=v;edge[tot].next=head[u];edge[tot].iscut=false;
    head[u]=tot++;
}
void Tarjan(int u,int pre)
{
    int v;
    low[u]=dfn[u]=++inde;
    st[top++]=u;
    inst[u]=true;
    int son=0;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        v=edge[i].to;
        if(v==pre)//注意!!
            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].iscut=true;
                edge[i^1].iscut=true;
            }
            //割点
            if(u!=pre&&low[v]>=dfn[u])//不是树根
            {
                iscut[u]=true;
                add_block[u]++;
            }
        }
        else if(low[u]>dfn[v])
             low[u]=dfn[v];
    }
    if(u==pre&&son>1)//树根,分支数大于1
        iscut[u]=true;
    if(u==pre)
        add_block[u]=son-1;
    inst[u]=false;
    top--;
}

void solve(int n)
{
    memset(dfn,0,sizeof(dfn));
    memset(inst,false,sizeof(inst));
    memset(add_block,0,sizeof(add_block));
    memset(iscut,false,sizeof(iscut));
    inde=top=0;
    bridge=0;
    for(int i=1;i<=n;i++)
        if(!dfn[i])
            Tarjan(i,i);

    int cut=0;//割点
    for(int i=1;i<=n;i++)
       if(iscut[i])
       {
           //printf("%d\n",i);
           cut++;
       }
    printf("%d\n",cut);

    printf("%d critical links\n",bridge);//桥
    vector<pp>ans;
    for(int u=1;u<=n;u++)
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(edge[i].iscut&&v>u)
                ans.push_back(make_pair(u,v));
        }
    sort(ans.begin(),ans.end());
    for(int i=0;i<ans.size();i++)
        printf("%d - %d\n",ans[i].first-1,ans[i].second-1);
    printf("\n");
}

int main()
{
    int n;
    while(scanf("%d",&n)==1)
    {
        init();

        //要保证正边和反边是相邻的,建无向图

        //UVA315
        int g[105][105];
        memset(g,0,sizeof(g));
        int u,v;
        scanf("%d",&u);
        while(u!=0)
        {
            while(getchar()!='\n')
            {
                scanf("%d",&v);
                addedge(u,v);
                addedge(v,u);//无向图
            }
            scanf("%d",&u);
        }

        //UVA796
        int u,v,k;
        for(int i=1;i<=n;i++)
        {
            scanf("%d (%d)",&u,&k);
            u++;
            while(k--)
            {
                scanf("%d",&v);
                v++;
                if(v<=u)//判重
                    continue;
                addedge(u,v);
                addedge(v,u);
            }
        }

        solve(n);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Cc_Sonia/article/details/82055107
今日推荐