Uva 10972

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 long
const 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值