进阶实验6-3.6 最小生成树的唯一性 (35分)

给定一个带权无向图,如果是连通图,则至少存在一棵最小生成树,有时最小生成树并不唯一。本题就要求你计算最小生成树的总权重,并且判断其是否唯一。

输入格式:

首先第一行给出两个整数:无向图中顶点数 N(≤)和边数 M。随后 M 行,每行给出一条边的两个端点和权重,格式为“顶点1 顶点2 权重”,其中顶点从 1 到N 编号,权重为正整数。题目保证最小生成树的总权重不会超过 2?30??。

输出格式:

如果存在最小生成树,首先在第一行输出其总权重,第二行输出“Yes”,如果此树唯一,否则输出“No”。如果树不存在,则首先在第一行输出“No MST”,第二行输出图的连通集个数。

输入样例 1:

5 7
1 2 6
5 1 1
2 3 4
3 4 3
4 1 7
2 4 2
4 5 5

输出样例 1:

11
Yes

输入样例 2:

4 5
1 2 1
2 3 1
3 4 2
4 1 2
3 1 3

输出样例 2:

4
No

输入样例 3:

5 5
1 2 1
2 3 1
3 4 2
4 1 2
3 1 3

输出样例 3:

No MST
2

对于最小生成树如果不唯一,那就说明最小生成树中的某条边可以换成其他一条同权值的边且保证仍然是最小生成树,如此只需要对最小生成树中权值不唯一的边进行删除并重新进行最小生成树的查找即可。

代码:
#include <cstdio>
#include <algorithm>
using namespace std;

int n,m,c,num;
struct line {
    int u,v,w;
}r[130000];
int f[501],tag[130000],tn,flag;
void init() {
    for(int i = 1;i <= n;i ++) {
        f[i] = i;
    }
}
int getf(int k) {
    return k == f[k] ? f[k] : (f[k] = getf(f[k]));
}
bool cmp(const line &a,const line &b) {
    return a.w < b.w;
}
bool check() {
    for(int i = 0;i < tn;i ++) {
        init();
        int d = 0,e = 0;
        for(int j = 0;j < m;j ++) {
            if(j == tag[i]) continue;
            if(getf(r[j].u) != getf(r[j].v)) {
                f[getf(r[j].u)] = getf(r[j].v);
                d += r[j].w;
                e ++;
            }
        }
        if(e == n - 1 && d == c) return 1;
    }
    return 0;
}
int main() {
    scanf("%d%d",&n,&m);
    init();
    for(int i = 0;i < m;i ++) {
        scanf("%d%d%d",&r[i].u,&r[i].v,&r[i].w);
    }
    sort(r,r + m,cmp);
    for(int i = 0;i < m;i ++) {
        if(getf(r[i].u) != getf(r[i].v)) {
            f[getf(r[i].u)] = getf(r[i].v);
            c += r[i].w;
            if(i < m - 1 && r[i].w == r[i + 1].w || i && r[i].w == r[i - 1].w) {
                flag = 1;
                tag[tn ++] = i;
            }
        }
    }
    for(int i = 1;i <= n;i ++) {
        if(getf(i) == i) num ++;
    }
    if(num != 1) printf("No MST\n%d",num);
    else printf("%d\n%s",c,!flag || !check() ? "Yes" : "No");
}

原文地址:https://www.cnblogs.com/8023spz/p/12304948.html

时间: 2024-10-27 09:32:36

进阶实验6-3.6 最小生成树的唯一性 (35分)的相关文章

进阶实验8-2.1 逆散列问题 (30分)

给定长度为 N 的散列表,处理整数最常用的散列映射是 (.如果我们决定用线性探测解决冲突问题,则给定一个顺序输入的整数序列后,我们可以很容易得到这些整数在散列表中的分布.例如我们将 1.2.3 顺序插入长度为 3 的散列表HT[]后,将得到HT[0]=3,HT[1]=1,HT[2]=2的结果. 但是现在要求解决的是“逆散列问题”,即给定整数在散列表中的分布,问这些整数是按什么顺序插入的? 输入格式: 输入的第一行是正整数 N(≤1000),为散列表的长度.第二行给出了 N 个整数,其间用空格分隔

POJ1679 The Unique MST(Kruskal)(最小生成树的唯一性)

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

poj1679(判断最小生成树的唯一性)

题目链接 : http://poj.org/problem?id=1679 1,图可能不是全部联通的,输出0(我的模板里没有这个判断) 2,首先做一次k..最小生成树算法,记录选取的边,然后枚举这些边,看在不考虑某条边(continue)的情况下是否还能得出和原来一样的最小cost(同样要考虑联通) 原文地址:https://www.cnblogs.com/lnu161403214/p/8367445.html

POJ-1679 The Unique MST (判断最小生成树的唯一性)

<题目链接> 题目大意: 给定一张无向图,判断其最小生成树是否唯一. 解题分析: 对图中每条边,扫描其它边,如果存在相同权值的边,则标记该边:用kruskal求出MST. 如果MST中无标记的边,则该MST唯一:否则,在MST中依次去掉标记的边,再求MST,若求得MST权值和原来的MST 权值相同,则MST不唯一. #include <cstdio> #include <iostream> #include <cstring> #include <al

The Unique MST——最小生成树(判断最小生成树的唯一性)

题目链接 题意: 给一个图,问其最小生成树是否唯一. 题解: 用Kruskal 算出最小生成树的值,并记录每一条边,然后枚举去掉这些边 看其是否也能构成最小生成树且值相同. 注意 在删边后,可能图构不成一棵树,得判断一下. 代码: #include<iostream> #include<stdio.h> #include<math.h> #include<algorithm> #include<vector> #include<map>

进阶实验2-3.1 海盗分赃 (25分)

P 个海盗偷了 D 颗钻石后来到公海分赃,一致同意如下分赃策略: 首先,P 个海盗通过抽签决定 1 - P 的序号.然后由第 1 号海盗提出一个分配方案(方案应给出每个海盗分得的具体数量),如果能够得到包括 1 号在内的绝对多数(即大于半数)同意,则按照该分配方案执行,否则 1 号将被投入大海喂鲨鱼:而后依次类似地由第 2 号.第 3 号等等海盗提出方案,直到能够获得绝对多数同意的方案出现为止,或者只剩下最后一位海盗,其独占所有钻石.请编写一个程序,给出第 1 号海盗的钻石分配方案中自己分得的钻

进阶实验6-3.2 社交网络图中结点的“重要性”计算 (30分)-dijkstra算法

解题思路:(邻接矩阵存储) 用dijkstra算法依次求出每个结点到其余结点的最短距离 #include <stdio.h> #include <string.h> #define INF 0x3f3f3f3f #define MaxVex 1000+10 int G[MaxVex][MaxVex]; int visit[MaxVex]; int Nv,Ne; void Init() { memset(G,INF,sizeof(G)); int i; for(i=1; i<=

进阶实验6-3.3 天梯地图 (30分)-Dijkstra

解题思路:采用Dijkstra算法,算两次,一次算最短时间,一次算最短路径,另开一数组记录路径 #include <stdio.h> #include <string.h> #define INF 0x3f3f3f3f #define MaxVex 500 typedef struct { int length; int time; } Graph; Graph G[MaxVex][MaxVex];//图 int visit[MaxVex]= {0};//访问标记 int fpat

进阶实验8-2.3 二叉搜索树的最近公共祖先 (30分)

解题思路: 1.定义一个结构体,来存储二叉排序树 typedef struct { int data; int left; int right; int parent; int h; } T; 2.再定义一个结构体,将输入数据存入 typedef struct { int data; int pos; } Info; 3.对输入数据排序 4.用二分法确实查询数据是否存在树中 5.寻找最近公共祖先 1)如果x,y均不是根结点 1.1.如果x==y,则x是y的祖先 1.2.若x,y分别在左右子树,则