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;
}