pku3352 Road Construction

#include <iostream>
using namespace std;

#define MAXN 1001
#define min(a,b) (a<b?a:b)

int p[MAXN],n,ecnt,m,dfn[MAXN],lowlink[MAXN],sign,deg[MAXN],color[MAXN],totcol;

struct Edge{
    
int v,next;
}edg[
10*MAXN];

void init(){
    ecnt
=0;
    sign
=0;
    memset(p,
-1,sizeof(p));
    memset(dfn,
-1,sizeof(dfn));
    memset(deg,
0,sizeof(deg));
    
    memset(color,
0,sizeof(color));
    totcol
=0;
}

void dfs(int pre,int u){
    
int i,v;
    dfn[u]
=lowlink[u]=++sign;
    
for(i=p[u];i!=-1;i=edg[i].next){
        v
=edg[i].v;
        
if(dfn[v]!=-1){
            
if(v!=pre)
                lowlink[u]
=min(lowlink[u],dfn[v]);
        }
        
else{
            dfs(u,v);
            lowlink[u]
=min(lowlink[u],lowlink[v]);
        }
    }
}

void flood(int u){
    
int i,v;
    
for(i=p[u];i!=-1;i=edg[i].next){
        v
=edg[i].v;
        
if(!color[v]){
            
if(dfn[u]<lowlink[v])
                color[v]
=++totcol;
            
else
                color[v]
=color[u];
            flood(v);
        }
    }
}




int solve(){
    
int i,u,v;
    dfs(
-1,1);
    
    color[
1]=++totcol;
    flood(
1);//着色区分图内各分量
    
    
for(u=1;u<=n;u++){
        
for(i=p[u];i!=-1;i=edg[i].next){
            v
=edg[i].v;
            
if(color[u]!=color[v])
                deg[color[u]]
++;//由于图是由两条相反的有向边表示无向边的,计算某结点的度只需计算其出度
        }
    }
    
    
int ans=0;
    
for(i=1;i<=totcol;i++)
        
if(deg[i]==1)//叶子的度为1
            ans++;
        
        
return ans;
}


int main(){
    
int i,u,v;
    
while(scanf("%d%d",&n,&m)!=EOF){
        init();
        
for(i=0;i<m;i++){
            scanf(
"%d%d",&u,&v);
            edg[ecnt].next
=p[u];
            edg[ecnt].v
=v;
            p[u]
=ecnt++;
            edg[ecnt].next
=p[v];
            edg[ecnt].v
=u;
            p[v]
=ecnt++;
        }
        printf(
"%d\n",(solve()+1)/2);//每添一条边,就选择树中的两个叶子结点,将它们连起来,于是最少的添边数目就是(叶子结点个数+1)/2
        
        
    }
    
return 0;
}
posted @ 2009-01-20 21:56  Beetlebum  阅读(262)  评论(0编辑  收藏  举报