zoukankan      html  css  js  c++  java
  • The Unique MST POJ

    求次小生成树思路: 先把最小生成树求出来  用一个Max[i][j] 数组把  i点到j 点的道路中 权值最大的那个记录下来 used数组记录该条边有没有被最小生成树使用过   把没有使用过的一条边加入最小生成树必然回形成一条回路   在这条回路中减去 除加入的边的权值最大的一条边  原图必然保持连通  (如果此时 权值最大的边和新加入的边权值相同  则存在 不同的最小生成树) 把每一条边加入再删除后 即可得出次小生成树 

    参考了: https://blog.csdn.net/qq_33951440/article/details/53084248  

         https://blog.csdn.net/li1615882553/article/details/80011884

         https://www.cnblogs.com/kuangbin/p/3147329.html

    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include<vector>
    #include<iostream>
    #include<cstring>
    int ans;
    const int maxn=1000+10;
    const int INF=100000000;
    int x[maxn],y[maxn];
    int cost[maxn][maxn];
    int pre[maxn];
    int lowc[maxn];
    int Max[maxn][maxn];
    int vis[maxn];
    int parent[maxn];
    int used[maxn][maxn];
    using namespace std;
    int prim(int cost[][maxn],int n){
        int ans=0;
           memset(vis,false,sizeof(vis));
        memset(Max,0,sizeof(Max));
        memset(used,false,sizeof(used));
        vis[0]=1;
        pre[0]=-1;
        for(int i=1;i<n;i++){
            lowc[i]=cost[0][i];//刚开始只有v0在生成树中  生成树和不在生成树的距离 就是v0和 其他点的距离
            pre[i]=0;
        }
        for(int i=1;i<n;i++){
            int minc=INF;
            int p=-1;
            for(int j=0;j<n;j++){
                if(!vis[j]&&minc>lowc[j]){//找出到树最短的变
                    minc=lowc[j];
                      p=j;
                }
            }
            if(p==-1)return -1; //不连通 
            ans+=minc;
            vis[p]=1;
            used[p][pre[p]]=used[pre[p]][p]=1;  //该边设置为已使用
            for(int j=0;j<n;j++){
                if(vis[j])Max[j][p]=Max[p][j]=max(Max[j][pre[p]],minc);//更新 j到p 的最大权值的边
                if(!vis[j]&&lowc[j]>cost[p][j]){
                    lowc[j]=cost[p][j]; //更新树到点的最短距离
                    pre[j]=p;//j点如果要进树 连p点 所以p就是j的父结点
                }
            }
        }
        return ans;
    
    }
    
    
    int smst(int cost[][maxn],int n){ //计算是否可以删除一条边  仍得到所有边权值不变
        int minnum=INF;
        for(int i=0;i<n;i++){
            for(int j=i+1;j<n;j++){
                if(cost[i][j]!=INF&&!used[i][j]){
                    minnum=min(minnum,ans+cost[i][j]-Max[i][j]);
                }
    
            }
        }
        return minnum;
    }
    
    int main()
    {
        int t;
        cin>>t;
        while(t--){
            int n,m;
            scanf("%d%d",&n,&m);
            int u,v,w;
            for(int i=0;i<n;i++){
                for(int j=0;j<n;j++){
                    if(i==j)cost[i][j]=0;
                    else cost[i][j]=INF;
                }
            }
            while(m--){
                int u,v,w;
                scanf("%d%d%d",&u,&v,&w);
                u--,v--;
                cost[u][v]=cost[v][u]=w;
            }
            ans=prim(cost,n);
            if(ans==smst(cost,n)){
                    printf("Not Unique!
    ");
            }
            else  printf("%d
    ",ans);
    
        }
        return 0;
    }
  • 相关阅读:
    MySQL手册
    字符串置换
    Java实现三角形计数
    Java实现求二叉树的路径和
    Excel催化剂开源第46波-按行列排列多个图形技术要点
    Excel催化剂开源第44波-窗体在Show模式下受Excel操作影响变为最小化解决方式
    Excel催化剂开源第45波-按原图大小导出图片
    个人永久性免费-Excel催化剂功能第105波-批量调整不规范的图形对象到单一单元格内存储
    Excel催化剂开源第42波-与金融大数据TuShare对接实现零门槛零代码获取数据
    Excel催化剂开源第43波-Excel选择对象Selection在.Net开发中的使用
  • 原文地址:https://www.cnblogs.com/ttttttttrx/p/9746365.html
Copyright © 2011-2022 走看看