Redundant Paths——构造双连通图

Posted j666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redundant Paths——构造双连通图相关的知识,希望对你有一定的参考价值。

题目链接

题意:

有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——构造双连通图的主要内容,如果未能解决你的问题,请参考以下文章

[POJ3177]Redundant Paths(双连通图,割边,桥,重边)

POJ 3177 Redundant Paths(强连通分量)

POJ 3177--Redundant Paths无向图添加最少的边成为边双连通图 &amp;&amp; tarjan求ebc &amp;&amp; 缩点构造缩点树(代

POJ3177 Redundant Paths

poj 3177 Redundant Paths(tarjan边双连通)

BZOJ 1718: [Usaco2006 Jan] Redundant Paths 分离的路径