The Unique MST POJ - 1679 次小生成树prim

求次小生成树思路: 先把最小生成树求出来  用一个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!\n");
        }
        else  printf("%d\n",ans);

    }
    return 0;
}

原文地址:https://www.cnblogs.com/ttttttttrx/p/9746365.html

时间: 2024-11-07 02:51:37

The Unique MST POJ - 1679 次小生成树prim的相关文章

The Unique MST POJ - 1679 (次小生成树)

Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undirected graph G = (V, E). A spanning tree of G is a subgraph of G, say T = (V', E'), with the following properties

POJ 1679 The Unique MST 【最小生成树/次小生成树】

The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 22668   Accepted: 8038 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undire

POJ 1679 次小生成树

The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 30015   Accepted: 10738 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undir

K - The Unique MST - poj 1679

题目的意思已经说明了一切,次小生成树... ************************************************************************************ #include<algorithm>#include<stdio.h>#include<string.h>#include<queue>using namespace std; const int maxn = 105;const int oo 

poj 2831 次小生成树模板

/*次小生成树 题意:给你一些路径,现在将一部分路径权值减少后问是否可以替代最小生成树里面的边. 解:次小生成树,即将这条边连上,构成一个环 求出任意两点路径之间的除了这条边的最大值,比较这个最大值>=这条边,说明可以替换. prime算法次小生成树模板 */ #include<stdio.h> #include<string.h> #define N 1100 #define inf 0x3fffffff int ma[N][N]; int Min(int a,int b)

poj 2831(次小生成树)

题意:给你一幅图,再给你Q个询问,每个询问为id cost,即如果将id这条边的边权改为cost的话,这条边是否可能是最小生成树中的一条边 解题思路:将第i条边(u,v)的权值修改的话,要判断是否是最小生成树中的一条边,首先要把它加入进去,此时必定会引起原来的生成树成环,所以必定要擦去一条边,擦去的是哪一条边,这就利用到了次小生成树的原理了. 之前写过一个次小生成树的题,现在回过头看,感觉又有点不对了. 这里再总结一次: 首先肯定是构造一颗最小生成树,接下来就是枚举不在生成树里的边,假定为(u,

ZOJ-1586 QS Network---最小生成树Prim

题目链接: https://vjudge.net/problem/ZOJ-1586 题目大意: 首先给一个t,代表t个测试样例,再给一个n,表示有n个QS装置,接下来一行是n个QS装置的成本.接下来是n*n的矩阵,表示每两个QS 装置之间链接需要的费用.求在全联通的情况下求最少费用. 思路: 这里需要求最少费用,由于点和边都有权值,索性直接把两端点的权值加到边的权值上,那就变成了一个裸的MST题目了 1 #include<iostream> 2 #include<cstdio> 3

POJ-1789 Truck History---最小生成树Prim算法

题目链接: https://vjudge.net/problem/POJ-1789 题目大意: 用一个7位的string代表一个编号,两个编号之间的distance代表这两个编号之间不同字母的个数.一个编号只能由另一个编号"衍生"出来,代价是这两个编号之间相应的distance,现在要找出一个"衍生"方案,使得总代价最小,也就是distance之和最小. 思路: 最小生成树模板题,这里是稠密图,应该用prim算法 直接在原来模板的基础上稍加改动即可 1 #inclu

poj1679次小生成树入门题

次小生成树求法:例如求最小生成树用到了 1.2.4这三条边,总共5条边,那循环3次的时候,每次分别不用1.2.4求得最小生成树的MST,最小的MST即为次小生成树 如下代码maxx即每次删去1,2,4边之后求得的最大边 #include<map> #include<set> #include<cmath> #include<queue> #include<stack> #include<vector> #include<cstd