ural 1416 Confidential 次小生成树

/*

题目:

   很裸的次小生成树题,要求先给出最小生成树的值,若有不连通的输出-1,

   接着需要输出次小生成树的值

  

分析:

   可以选择prim或kruskal算法做,我的做法是用prim做的,具体看代码注释

 

*/

#include <iostream>

#include <cstring>

#include <cstdio>

using namespace std;

#define X 503

#define INF 10000000

int path[X][X],map[X][X],dis[X],pre[X],n,m;

bool use[X],visit[X][X];

int prim()

{

   memset(pre,0,sizeof(pre));        //前趋顶点

   memset(visit,false,sizeof(visit)); //标记该边是否在最小生成树中

   memset(use,false,sizeof(use));    //标记该边是否已经在最小生成树中

   memset(path,0,sizeof(path));      //标记该两顶点之间的最大长度的边

   for(int i=1;i<=n;i++)

      dis[i] = INF;

   dis[1] = 0;

   int k,MIN,ans = 0;

   for(int i=0;i<n;i++)

   {

      MIN = INF;

      for(int j=1;j<=n;j++)

         if(!use[j]&&dis[j]<MIN)

            MIN = dis[k=j];

      if(MIN==INF)          //若当前就没有连通路的话,直接退出

         return INF;

 

      int p = pre[k];

      visit[p][k] = visit[k][p] = true;//表示该边在生成树中

      path[p][k] = MIN;           //表示最小生成生成树中的边的长度

      for(int j=1;j<=n;j++)

         if(use[j])         //更新所有已在最小生成树中的点到k的距离path[j][k]

            path[j][k] = path[j][p]>path[p][k]?path[j][p]:path[p][k];

     

      ans += MIN;

      use[k] = true;

      for(int j=1;j<=n;j++)

         if(!use[j]&&dis[j]>map[k][j])

            dis[j] = map[k][j],pre[j] = k;//如果k能把dis[j]更新,表示k是j的pre

   }

   return ans;

}

int main()

{

   freopen("sum.in","r",stdin);

   freopen("sum.out","w",stdout);

   int x,y,z;

   while(cin>>n>>m)

   {

      for(int i=1;i<=n;i++)

         for(int j=1;j<=n;j++)

            map[i][j] = INF;

      while(m--)

      {

         scanf("%d%d%d",&x,&y,&z);

         map[x][y] = map[y][x] = z;

      }

      int ans = prim();     //求出一棵最小生成树

      if(ans==INF)

      {

         cout<<"Cost: "<<-1<<endl;

         cout<<"Cost: "<<-1<<endl;

      }

      else

      {

         cout<<"Cost: "<<ans<<endl;

         int ans2 = INF;

         for(int i=1;i<=n;i++)

            for(int j=1;j<=n;j++)

                if(!visit[i][j]&&map[i][j]<INF)

                {//枚举边,若不在最小生成树中时,且该边是连通的,用它替换最小生成树中的一条边

                   int temp = ans+map[i][j]-path[i][j];

                  if(temp<ans2)

                      ans2 = temp;

                }

                if(ans2==INF)

                   cout<<"Cost: "<<-1<<endl;

                else

                   cout<<"Cost: "<<ans2<<endl;

      }

   }

   return 0;

}

 

posted @ 2012-03-31 18:24  yejinru  阅读(188)  评论(0编辑  收藏  举报