POJ3177 Redundant Paths

双连通图:无向图中每两个顶点都存在完全不同的两条路径

给定一个无向图,问要给它增加多少条边可以把它变成双连通图。

用tarjan缩点,可以得到一棵树,添加(叶子结点+1)/2条边可以使其成环,也就是答案~

为了避开重边,这题用邻接矩阵存,wa了一晚上QAQ~

#include<cstdio>
#include<algorithm>
#include<vector>
#include<stack>
using namespace std;
const int maxn=5014;
int g[maxn][maxn];
int N,M,x,y;
int low[maxn];
int dfn[maxn];
stack<int> st;
int cnt;
int scc;
int pos[maxn];
int in[maxn];
void tarjan (int x,int pre) {
    low[x]=dfn[x]=++cnt;
    st.push(x);
    for (int i=1;i<=N;i++) {
        if (i==pre) continue;
        if (!g[x][i]) continue;
        if (!low[i]) {
            tarjan(i,x);
            low[x]=min(low[x],low[i]);
        }
        else if (!pos[i]) low[x]=min(low[x],dfn[i]);
    }
    if (low[x]==dfn[x]) {
        scc++;
        while (1) {
            int u=st.top();
            st.pop();
            low[u]=low[x];
            pos[u]=scc;
            if (u==x) break;
        }
    }
}
void build () {
    for (int i=1;i<=N;i++) {
        for (int j=1;j<=N;j++) {
            if (pos[i]!=pos[j]&&g[i][j]) in[pos[j]]++;
        }
    }
}
int main () {
    scanf ("%d %d",&N,&M);
    for (int i=0;i<M;i++) {
        scanf ("%d %d",&x,&y);
        g[x][y]=g[y][x]=1;
    }
    for (int i=1;i<=N;i++) 
    if (!low[i]) tarjan(i,i);
    build ();
    int leaves=0;
    for (int i=1;i<=scc;i++) {
        if (in[i]==1) leaves++;
    }
    printf ("%d\n",(leaves+1)/2);
    return 0;
}

 

posted @ 2020-02-15 20:13  zlc0405  阅读(102)  评论(0编辑  收藏  举报