次小生成树

次小生成树
http://acm.cs.ecnu.edu.cn/problem.php?problemid=2165
找了个次小生成树的题目做一做。

方法是先找出最小生成树,然后依次添加每条在原图中,而不在MST上的边,然后删除
形成的环上的最大边(先通过dfs预处理求出MST上任意点之间的最大边权),这样
形成了一棵新树,找出所有添加删除形成的secondary minimum spanning tree就OK了!


#include  < stdio.h >
#include
< string .h >
#define  INF 2139062143
int  m,n,min_dif,flag,lowcost[ 501 ],map[ 501 ][ 501 ],mst_map[ 501 ][ 501 ],
    s[
501 ],pre[ 501 ],max_val[ 501 ][ 501 ],vis[ 501 ];
void  dfs( int  sta, int  t, int  max){
    
for ( int  i = 1 ;i <= n;i ++ ){
        
if ( ! vis[i]  &&  mst_map[t][i] != INF){
            vis[i]
= 1 ;
            
int  tmp = max;
            
if (mst_map[t][i] > max) max = mst_map[t][i];
            
if (max > max_val[sta][i]) max_val[sta][i] = max_val[i][sta] = max;
            dfs(sta,i,max);
            max
= tmp;
        }
    }

}
int  main(){
    
while (scanf( " %d%d " , & n, & m) != EOF){
        memset(map,
127 , sizeof (map));
        memset(mst_map,
127 , sizeof (mst_map));
        memset(lowcost,
127 , sizeof (lowcost));
        memset(s,
0 , sizeof (s));
        memset(pre,
0 , sizeof (pre));
        memset(max_val,
128 , sizeof (max_val));
        
int  i,j,idx,min_mst = 0 ,mincost,a,b,c;
        
for (i = 1 ;i <= m;i ++ ){
            scanf(
" %d%d%d " , & a, & b, & c);
            map[a][b]
= map[b][a] = c;
        }
        
// prim algorithm
        lowcost[ 1 ] = 0 ;
        
for (i = 1 ;i <= n;i ++ ){
            mincost
= INF;
            
for (j = 1 ;j <= n;j ++ )
                
if ( ! s[j]  &&  lowcost[j] < mincost){
                    mincost
= lowcost[j];
                    idx
= j;
                }
            s[idx]
= 1 ;
            min_mst
+= mincost;
            mst_map[idx][pre[idx]]
= mst_map[pre[idx]][idx] = map[pre[idx]][idx];
            
for (j = 1 ;j <= n;j ++ ){
                
if ( ! s[j]  &&  map[idx][j] < lowcost[j]){
                    lowcost[j]
= map[idx][j];
                    pre[j]
= idx;
                }
            }
        }
        
// calc max_val[i][j] 
         for (i = 1 ;i <= n;i ++ ){
            memset(vis,
0 , sizeof (vis));
            vis[i]
= 1 ;
            dfs(i,i,
- INF);
        }
        
// for each edge excluded int the MST
        
// try to get secondary minimum spanning tree
        min_dif = INF;flag = 0 ;
        
for (i = 1 ;i <= n;i ++ ){
            
for (j = i + 1 ;j <= n;j ++ ){
                
if (mst_map[i][j] == INF  &&  map[i][j] != INF){
                    flag
= 1 ; // mark if there's s new tree
                     if (map[i][j] - max_val[i][j] < min_dif) min_dif = map[i][j] - max_val[i][j];
                }
            }    
        }
        
if ( ! flag) printf( " %d -1\n " ,min_mst);
        
else  printf( " %d %d\n " ,min_mst,min_mst + min_dif);
    }
    
return   0 ;
}


你可能感兴趣的:(次小生成树)