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

你可能感兴趣的:(struct)