poj 3177 3352 边双连通分量

来源:互联网 发布:唱歌培训软件 编辑:程序博客网 时间:2024/05/01 14:30

题目链接:http://poj.org/problem?id=3177
题意:至少加多少边才能构成边双连通图。
思路:求边双连通分量,对于每一个边双连通分量都看做一个点,也就是进行缩点,然后就构造出一个树,然后在这个树上加多少个树边,能够变成一个双连通图。 加的数量就是( 这棵树总度数为1的结点数 + 1 )/ 2

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <stack>using namespace std;const int M_node = 5009,M_edge = 20009;struct edge{    int to,next;    bool cut;}edge[M_edge];stack<int> st;int head[M_node],tot;int low[M_node],dfn[M_node],belong[M_node];int degree[M_node];int dfs_clock,block,bridge;bool instack[M_node];int n,m;void init(){    while(!st.empty()) st.pop();    memset(head,-1,sizeof(head));    memset(degree,0,sizeof(degree));    tot = 0;    memset(instack,false,sizeof(instack));    memset(belong,-1,sizeof(belong));    dfs_clock = 0;    block = bridge = 0;}void add_edge(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 fa){    low[u] = dfn[u] = ++dfs_clock;    st.push(u);    instack[u] = true;    for(int i = head[u]; i != -1 ;i = edge[i].next)    {        int v = edge[i].to;        if(v == fa) continue;        if(!dfn[v])        {            tarjan(v,u);            low[u] = min(low[u],low[v]);            if(low[v] > dfn[u])            {                bridge++;                edge[i].cut = true;                edge[i^1].cut = true;            }        }        else if(instack[u] && low[u] > dfn[v]) low[u] = dfn[v];    }    if(low[u] == dfn[u])    {        block++;        for(;;)        {            int v = st.top();            st.pop();            instack[v] = false;            belong[v] = block;            if(v == u) break;        }    }}void solve(){    int ans = 0;    tarjan(1,-1);    for(int i = 1;i <= n;i++)    {        for(int j = head[i];j != -1;j = edge[j].next)        {            if(edge[j].cut) degree[belong[i]]++;        }    }    for(int i = 1;i <= block;i++)    {        if(degree[i] == 1) ans++;    }    printf("%d\n",(ans+1)/2);}int main(){    while(scanf("%d %d",&n,&m) == 2)    {        init();        for(int i = 0;i < m;i++)        {            int a,b;            scanf("%d %d",&a,&b);            add_edge(a,b);            add_edge(b,a);        }        solve();    }    return 0;}
0 0
原创粉丝点击