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;
}
posted @ 2008-10-24 20:38  Hdu-Lost  阅读(693)  评论(0编辑  收藏  举报