poj 3352 Road Construction(边双连通分量)

来源:互联网 发布:jdbc无法连接数据库 编辑:程序博客网 时间:2024/05/22 06:29

Problem:
给一个图,问最少连多少条边可以使原图成为一个双连通分量。
Solution:
求出所有的双连通分量,缩点,看成一棵树,此时度为1的点就是叶子,而一颗度为x的树想要变成双连通图至少需要(x+1)/2条边(x/2向上取整),可以理解为一条边可以使两个点连接。

#include<cstdio>#include<iostream>#include<sstream>#include<cstdlib>#include<cmath>#include<cctype>#include<string>#include<cstring>#include<algorithm>#include<stack>#include<queue>#include<set>#include<map>#include<ctime>#include<vector>#include<fstream>#include<list>using namespace std;#define ms(s) memset(s,0,sizeof(s))typedef unsigned long long ULL;typedef long long LL;const double PI = 3.141592653589;const int INF = 0x3fffffff;const int maxn = 1005;int n, times, bcc_cnt, dfn[maxn], low[maxn], bccno[maxn];vector<int> G[maxn];bool isB[maxn][maxn];void tarjan(int u, int fa){//找到桥    dfn[u] = low[u] = ++times;    for(int i = 0; i < G[u].size(); ++i){        int v = G[u][i];        if(!dfn[v]){            tarjan(v, u);            low[u] = min(low[u], low[v]);            if(low[v] > dfn[u])                isB[u][v] = isB[v][u] = true;        }        else if(fa != v)            low[u] = min(low[u], dfn[v]);    }}void dfs(int idx){//给边双连通分量标记    dfn[idx] = 1;    bccno[idx] = bcc_cnt;    for(int i = 0; i < G[idx].size(); ++i){        int v = G[idx][i];        if(isB[idx][v])            continue;        if(!dfn[v])            dfs(v);    }}void find_ebcc(){    bcc_cnt = times = 0;    memset(dfn,0,sizeof(dfn));    memset(low,0,sizeof(low));    memset(bccno,0,sizeof(bccno));    memset(isB,0,sizeof(isB));    for(int i = 1; i <= n; ++i){//求出桥        if(!dfn[i]){            bcc_cnt++;            tarjan(i, -1);        }    }    memset(dfn,0,sizeof(dfn));    for(int i = 1; i <= n; ++i){//将点标记        if(!dfn[i]){            bcc_cnt++;            dfs(i);        }    }}int d[maxn];int solve(){    find_ebcc();    memset(d,0,sizeof(d));    for(int i = 1; i <= n; ++i){        for(int j = 0; j < G[i].size(); ++j){            if(bccno[i] != bccno[G[i][j]]){                d[bccno[i]]++;  d[bccno[G[i][j]]]++;            }        }    }    int tot = 0;    for(int i = 1; i <= bcc_cnt; ++i){        if(d[i] == 2)            tot++;    }    return (tot+1)/2;}int main(){//    freopen("E:\\input.txt","r",stdin);//    freopen("/home/really/Document/output","w",stdout);//    ios::sync_with_stdio(false);    int t, a, b;    while(~scanf("%d%d", &n,&t)){        for(int i = 1; i <= n; ++i)            G[i].clear();        for(int i = 0; i < t; ++i){            scanf("%d%d", &a,&b);            G[a].push_back(b);            G[b].push_back(a);        }        int ans = solve();        printf("%d\n",ans);    }    return 0;}
0 0