Uva 10972

来源:互联网 发布:ps淘宝详情页制作步骤 编辑:程序博客网 时间:2024/06/06 00:03

Uva 10972

题意是给一个无向图,要求将所有边改为有向边,求还需要添加多少有向边才能使其强连通。
寻找边双联通分量,先深搜一次,标记所有桥,再深搜一次,不经过桥,找出所有边双联通分量,之后建新图,把一个联通分量看做一个点,计算所有点的度数,度数小于2的点需要将度数提升至2才能保证强连通。因此ans=(∑(2-deg[i])+1)/2,(deg[i]<2)。
当边双联通分量只有一个时,原图已经强连通,因此不用加边。

#include<vector>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;#define debug puts("Infinity is awesome!")#define mm(a,b) memset(a,b,sizeof(a))#define LS (root<<1)#define RS (root<<1|1)#define LSON LS,l,mid#define RSON RS,mid+1,r#define LL long longconst int Inf=1e9+7;const int maxn=1e3+5;const int maxe=maxn*maxn*2;struct Edge{    int from ,to, next;    Edge(){}    Edge(int a,int b,int c):from(a),to(b),next(c){}};int dfs_clock;int head[maxn];int dfn[maxn];int isbridge[maxe];int ecnt;Edge edges[maxe];void init(){    mm(head,-1);    mm(dfn,0);    mm(isbridge,0);    dfs_clock=0;    ecnt=0;}int dfs(int u,int fa){    int lowu=dfn[u]=++dfs_clock;    for(int i=head[u];i!=-1;i=edges[i].next){        int v=edges[i].to;        if(!dfn[v]){            int lowv=dfs(v, u);            lowu=min(lowu,lowv);            if(lowv>lowu)                isbridge[i]=isbridge[i^1]=1;        }else if(dfn[v]<dfn[u]&&v!=fa){            lowu=min(lowu,dfn[v]);        }    }    return lowu;}void add_edge(int u,int v){    edges[ecnt]=Edge(u,v,head[u]);    head[u]=ecnt++;    edges[ecnt]=Edge(v,u,head[v]);    head[v]=ecnt++;}int Bcc[maxn], bcnt;int deg[maxn];void dfs(int u){    Bcc[u]=bcnt;    for(int i=head[u];i!=-1;i=edges[i].next){        if(isbridge[i]) continue;        int v=edges[i].to;        if(Bcc[v]) continue;        dfs(v);    }}int main(){    int n, m;    int u, v;    int cas=0;    while(~scanf("%d%d",&n, &m)){        init();        for(int i=0;i<m;i++){            scanf("%d%d",&u,&v);            add_edge(u,v);        }        for(int i=1;i<=n;i++)        if(!dfn[i]) dfs(i,-1);        mm(Bcc,0); bcnt=0;        for(int i=1;i<=n;i++)        if(!Bcc[i]) bcnt++, dfs(i);        if(bcnt==1) {puts("0"); continue;}        mm(deg,0);        for(int i=0;i<ecnt;i++){            u=edges[i].from, v=edges[i].to;            if(Bcc[u]!=Bcc[v]) deg[Bcc[v]]++;        }        int ans=0;        for(int i=1;i<=bcnt;i++)        if(deg[i]<2)            ans+=2-deg[i];        printf("%d\n",(ans+1)/2);    }    return 0;}
0 0
原创粉丝点击