zoukankan      html  css  js  c++  java
  • 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;

    }

  • 相关阅读:
    Windows Server 2016-Active Directory复制概念(二)
    Windows Server 2016-Active Directory复制概念(一)
    Windows Server 2016-Wbadmin命令行备份域控制器
    Windows Server 2016-图形化备份域控制器
    Windows Server 2016-Nano Server介绍
    Windows Server 2016-系统安装软硬件要求
    每天一个linux命令(51)--grep命令
    每天一个linux命令(50)--date命令
    每天一个linux命令(49)--diff命令
    每天一个linux命令(48)--ln命令
  • 原文地址:https://www.cnblogs.com/yejinru/p/2427495.html
Copyright © 2011-2022 走看看