码迷,mamicode.com
首页 > 其他好文 > 详细

Redundant Paths——构造双连通图

时间:2019-10-07 16:13:31      阅读:121      评论:0      收藏:0      [点我收藏+]

标签:另一个   scanf   str   else   ons   tarjan   scan   print   one   

题目链接

题意:

有n个牧场,Bessie 要从一个牧场到另一个牧场,要求至少要有2条独立的路可以走。现已有m条路,求至少要新建多少条路,使得任何两个牧场之间至少有两条独立的路。两条独立的路是指:没有公共边的路,但可以经过同一个中间顶点。
该图中为连通图

题解:

题意转换一下:

就是给了一个连通图,问加多少条边可以变成边双连通。

双连通图

我们将原图先缩点, 可以得到一棵树.然后我们统计叶子节点数目leaf(即度为1的点), 最小的加边数即(leaf+1)/2 (成对加边)

考虑重边

 

代码:

技术图片
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include<vector>
#include <map>
using namespace std;

const int maxn = 5010;//点数
const int maxm = 20010;//边数,因为是无向图,所以这个值要*2

struct Edge
{
    int to,next;
    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];
void addedge(int u,int v)
{
    edge[tot].to = v;
    edge[tot].next = head[u];
    edge[tot].cut=false;
    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;
    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].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;
        }
        while( v!=u );
    }

}
void init()
{
    tot = 0;
    memset(head,-1,sizeof(head));
}
int du[maxn];
void solve(int n)
{
    memset(dfn,0,sizeof(dfn));
    memset(Instack,false,sizeof(Instack));
    memset(du,0,sizeof du);
    memset(cut,0,sizeof cut);
    Index = top = scc = 0;
    bridge = 0;
    for(int i = 1; i <= n; i++)
        if(!dfn[i])
            Tarjan(i,i);
    for(int i = 1; i <= n; i++)
        for(int j = head[i]; j != -1; j = edge[j].next)
            if(edge[j].cut)
                du[belong[i]]++;
    int ans=0;
    for(int i = 1; i <= scc; i++)
        if(du[i]==1)
            ans++;
    //找叶子结点的个数ans,构造边双连通图需要加边(ans+1)/2
    printf("%d\n",(ans+1)/2);

}
int main()
{
    int n,m;
    int u,v;
    while(scanf("%d%d",&n,&m)==2)
    {
        init();
        while(m--)
        {
            scanf("%d%d",&u,&v);
            addedge(u,v);
            addedge(v,u);
        }
        solve(n);
    }
    return 0;
}
View Code

 

Redundant Paths——构造双连通图

标签:另一个   scanf   str   else   ons   tarjan   scan   print   one   

原文地址:https://www.cnblogs.com/j666/p/11630735.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!