PKU 3352(图的关键边)

觉得这道题目蛮有意义的

首先求割边 缩图成树 计算叶子结点与根结点连通所需要添加的最少边既可

 

 

#include  < iostream >
using   namespace  std;
// 点编号从1开始
typedef  struct
{
    
long  v,next;
}Edge;

const   long  MAXN = 2000 ;

long  du[MAXN]; 
long  p[MAXN];
Edge e[MAXN];
long  eid;

long  dfn[MAXN], low[MAXN], deep, color[MAXN], com;
long  n,r;

inline 
void  insert( long  from, long  to)
{
    e[eid].next
= p[from];
    e[eid].v
= to;
    p[from]
= eid ++ ;
    
    
// 以下为无向图使用
    
    swap(from, to);
    
    e[eid].next
= p[from];
    e[eid].v
= to;
    p[from]
= eid ++ ;
    
}

long  min( long  a, long  b)
{
    
return  a < b ? a:b;
}

inline 
void  dfs( int  i,  int  f)

    dfn[i] 
=  low[i]  =   ++ deep;
    
long  j;
    
for  (j  =  p[i]; j  !=- 1 ; j = e[j].next)
    {
        
int  k  =  e[j].v;
        
if  ( ! dfn[k])
        {
            dfs(k, i);
            low[i] 
=  min(low[i], low[k]);
        }
        
else   if  (k  !=  f)
        {
            low[i] 
=  min(low[i], dfn[k]);
        }
    }
}
inline 
void  set_color( int  i)
{
     
long  j;
     
for  (j  =  p[i]; j  !=- 1 ; j = e[j].next)
    {
        
int  k  =  e[j].v;
        
if  ( ! color[k])
        {
            
if  (low[k]  >  dfn[i]) color[k]  =   ++ com;
            
else  color[k]  =  color[i];
            set_color(k);
        }
    }
}

inline 
void  biconnect()
{
    deep
= 0 ;
    dfs(
1 , - 1 );
    com
= 1 ;
    color[
1 ] = 1 ;
    set_color(
1 );            
}

int  main()
{
    
    
while (scanf( " %ld %ld " , & n, & r) != EOF)
    {
     
        
long  i,j;
        memset(p,
- 1 , sizeof (p));
        memset(du,
0 , sizeof (du));
        memset(low,
0 , sizeof (low));
        memset(color,
0 , sizeof (color));
        memset(dfn,
0 , sizeof (dfn));
        eid
= 0 ;
        
        
for (i = 0 ;i < r; ++ i)
        {
            
long  from,to;
            scanf(
" %ld %ld " , & from, & to);
            insert(from,to);
        }

        
        
// 关键边求解
         biconnect();
        
        
for  (i  =   1 ; i  <=  n; i ++ )
        {
            
long  a  =  color[i];
            
for  (j  =  p[i]; j  !=- 1 ; j = e[j].next)
            {
                
long  b  =  color[e[j].v];
                
if  (a  !=  b)
                {
                    
++ du[a];
                }
            }
        }

        
long  leap  =   0 ;
        
        
for  (i  =   1 ; i  <=  com; i ++ )
        {
            
if  (du[i]  ==   1 )
            {
                
++ leap;
            }
        }
        
        printf(
" %ld\n " , (leap + 1 ) / 2 );
 
    }
    
return   0 ;
}

你可能感兴趣的:(pku)