poj3352 利用边的双连通性质求解

来源:互联网 发布:阿里跟汉聚网络的关系 编辑:程序博客网 时间:2024/05/16 01:44

给你一个无向图,求解至少需要添加几条边,就能保证删除任一条边时,图仍然是连通的
思路:
求解至少添加多少条边,可以使该图成为边的双连通图
利用tarjan算法:求解low[]值记录父亲结点,然后low[]相同的点,在一个连通分量中,然后缩点
求解出度为1的点的个数ans,答案就是(ans+1)/2;
#include<iostream>#include<algorithm>#include<cstdio>#include<vector>#include<string.h>using namespace std;const int Max=1111;int low[Max];int dfn[Max];int cnt;int Branch;int dre[Max];vector<int>Gra[Max];int MIN(int a,int b){    return a>b?b:a;}void tarjan(int x,int fa){    low[x]=dfn[x]=cnt++;    for(int i=0;i<Gra[x].size();i++)    {        int u=Gra[x][i];        if(u==fa) continue;        if(!dfn[u])        {            tarjan(u,x);            low[x]=MIN(low[x],low[u]);        }        else if(low[x]>dfn[u])        low[x]=dfn[u];    }}void start(int n ){    memset(dfn,0,sizeof(dfn));    cnt=1;    Branch=0;    for(int i=1;i<=n;i++)    {        if(!dfn[i])        {            tarjan(i,i);            Branch++;        }    }}int main(){    int n,m;    while(scanf("%d%d",&n,&m)!=EOF)    {        memset(dre,0,sizeof(dre));        for(int i=1;i<Max;i++)         Gra[i].clear();        for(int i=1;i<=m;i++)        {            int u,v;            scanf("%d%d",&u,&v);            Gra[u].push_back(v);            Gra[v].push_back(u);        }        start(n);        for(int i=1;i<=n;i++)        {            for(int j=0;j<Gra[i].size();j++)            {                if(low[i]!=low[Gra[i][j]])//记录出度:                  dre[low[i]]++;            }        }        int  ans=0;        for(int i=1;i<cnt;i++)         if(dre[i]==1)           ans++;        printf("%d\n",(ans+1)/2);    }    return 0;}

原创粉丝点击