-
2020-05-13 17:05:55
7-24 最小生成树的唯一性 (35分)
给定一个带权无向图,如果是连通图,则至少存在一棵最小生成树,有时最小生成树并不唯一。本题就要求你计算最小生成树的总权重,并且判断其是否唯一。
输入格式:
首先第一行给出两个整数:无向图中顶点数 N(≤500)和边数 M。随后 M 行,每行给出一条边的两个端点和权重,格式为“顶点1 顶点2 权重”,其中顶点从 1 到N 编号,权重为正整数。题目保证最小生成树的总权重不会超过 230。
输出格式:
如果存在最小生成树,首先在第一行输出其总权重,第二行输出“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
这个题不单单是让求最小生成树的总路径长度,而且还让判断最小生成树的唯一性。因为对并查集印象比较深刻,我首先想到了克鲁斯卡尔算法,可在判断最小生成树的唯一性上老是出错,最后不得已,剽窃了他人的劳动成果,将自己写的代码按照别人的想法做了修改,结果就过了,不过心里还是很不爽。在思考过程中,我甚至想到了“去边法重新构造法”,这种方法十有八九会超时,就把这个方案否决了。用Prim算法可能更直接,不过我和Prim算法还不是很熟,也把这个方法舍弃了。这个题的Kruskal解法见如下代码:
#include <iostream> #include <algorithm> using namespace std; struct Book{ int u,v,w; }book[125010]; int V[520],ans = 0; int p[520],r[520]; int G[520][520]={0}; bool cmp(Book a,Book b){ if(a.w!=b.w) return a.w<b.w; return false; } void Init(int n) { for(int i=0;i<=n;i++) { r[i] = 0; p[i] = i; } } int Find(int x){ return x==p[x]?x:p[x]=Find(p[x]); } void Union(int x,int y) { x = Find(x);y=Find(y); if(x==y)return ; if(r[x]>r[y]) p[y] = x; else if(r[y]>r[x]) p[x] = y; else{ p[x] = y; r[y]++; } } int main() { //freopen("in","r",stdin); int n,m;scanf("%d%d",&n,&m);Init(n); for(int i=0;i<m;i++) scanf("%d%d%d",&book[i].u,&book[i].v,&book[i].w); sort(book,book+m,cmp); int cnt = 0,all = 0,flag = 0; for(int i=0;i<m;i++){ int pu,pv; int u = book[i].u,v=book[i].v; u=Find(u),v=Find(v); if(u!=v){ for(int j=i+1;j<m;j++){ if(book[j].w==book[i].w){ pu=Find(book[j].u);pv=Find(book[j].v); if((pu==u&&pv==v)||(pv==u&&pu==v)) flag=1; }else{ break; } } Union(u,v); cnt++; all+=book[i].w; } } if(cnt==n-1) { printf("%d\n",all); if(flag) printf("No\n"); else printf("Yes\n"); }else{ printf("No MST\n"); cnt = 0; for(int i=1;i<=n;i++) if(p[i]==i)cnt++; printf("%d\n",cnt); } return 0; }
更多相关内容 -
判断最小生成树的唯一性
2022-04-06 20:57:55什么样的边会影响到最小生成树的唯一性呢? kruskal 求最小生成树 是将所有边权从小到大排序,然后判断当前边的两个端点所在连通块是否连通。如果没有连通,那么这条边就需要拿。 而此时如果有另外一条边,虽然先来看一个例题:Forsaken喜欢独一无二的树
题意:
现在给定一个 n n n 个点, m m m 条边的图,每条边 e i e_{i} ei 都有一个权值 w i w_{i} wi 。刚开始最小生成树可能不唯一,现在可以删除一些边,使得剩下的边的最小生成树大小不变并且唯一。
求删除的边的权值和最小是多少?
分析:
什么样的边会影响到最小生成树的唯一性呢?kruskal 求最小生成树 是将所有边权从小到大排序,然后判断当前边的两个端点所在连通块是否连通。如果没有连通,那么这条边就需要拿。
而此时如果有另外一条边,虽然也可以将这两个连通块合并,但是其权值比较大,那么这条边是不会影响到最小生成树的。
所以,只有两个边的权值相同,并且都能将端点的两个连通块合并,这么这两个边选择哪个都行,那么最小生成树就不唯一了。所以,为了保证最小生成树唯一,那么就是要去掉若干条 权值相同并且能够合并相同连通块的边,只剩一个这样的边就行。
如何实现呢?
我们像 kruskal 一样将所有的边按照权值排序,从小到大遍历所有的边。
对于当前边来说,将所有的和当前边权相等的边都拿过来(双指针)。对于这些权值相同的边,我们要去掉一些能够合并相同连通块的边。我们可以先将所有的权值相同且能够合并连通块的边都删除,然后再留下最小生成树中的边。
这样,对于权值相同的能够合并连通块的多余边就被删除了。- 先遍历所有边,判断其是否可选,也就是判断其端点连接的两个连通块是否已经连通。如果没有连通,说明可选,删除的权值和
ans += wi
;
这时,我们把能够合并连通块的所有边都删除了。 - 然后,再遍历一遍,用这些边求最小生成树权值和
sum
。
最终,删除的多余边权之和就为
ans - sum
。int sum = 0; for(int i=1;i<=m;i++) { int r = i; while(r <= m && a[r].w == a[i].w) r++; r--; for(int j=i;j<=r;j++) { int x = a[j].x, y = a[j].y, w = a[j].w; if(find(x) != find(y)) ans += w; } for(int j=i;j<=r;j++) { int x = a[j].x, y = a[j].y, w = a[j].w; if(find(x) != find(y)) pre[find(x)] = find(y), sum += w; } i = r; } ans -= sum;
完整Code:
#include<bits/stdc++.h> using namespace std; #define Ios ios::sync_with_stdio(false),cin.tie(0) #define mem(a,b) memset(a,b,sizeof a) #define int long long #define PII pair<int,int> #define pb push_back #define fi first #define se second #define endl '\n' map<PII,int> mp; /**/ const int N = 200010, mod = 1e9+7; int T, n, m; struct node{ int x, y, w; }a[N]; int ans, pre[N]; bool cmp(node a, node b){ return a.w < b.w; } int find(int x){ if(pre[x] != x) pre[x] = find(pre[x]); return pre[x]; } void kruskal() { sort(a+1, a+m+1, cmp); int sum = 0; for(int i=1;i<=m;i++) { int r = i; while(r <= m && a[r].w == a[i].w) r++; r--; for(int j=i;j<=r;j++) { int x = a[j].x, y = a[j].y, w = a[j].w; if(find(x) != find(y)) ans += w; //能拿的都删去 } for(int j=i;j<=r;j++) { int x = a[j].x, y = a[j].y, w = a[j].w; if(find(x) != find(y)) pre[find(x)] = find(y), sum += w; //求最小生成树 } i = r; } ans -= sum; //把最小生成树的权值留下,删去的就是多余的了 } signed main(){ Ios; cin>>n>>m; for(int i=1;i<=n;i++) pre[i] = i; for(int i=1;i<=m;i++) { int x, y, w;cin>>x>>y>>w; a[i] = {x, y, w}; } kruskal(); cout << ans; return 0; }
这样,阻碍最小生成树唯一的边就都被删去了。
那么,如果需要判断一个图中最小生成树是否唯一,那么就可以用这种方法,看最终的删去边的权值是否为0,如果为0就是唯一的。
或者,也可以对于每一种权值来说,判断这其中的 可拿的边(端点所在连通块不连通) 是不是都在最小生成树中,如果有的不在,则说明最小生成树不唯一。因为既然一个边可拿,也就是端点所在连通块不连通,那么其就应该出现在最小生成树中。而现在第二遍遍历跑最小生成树之后,发现之前可拿边的个数和可拿边的个数不同,那么也就是有多余的边,最小生成树不唯一。
Code:
#include<iostream> #include<algorithm> using namespace std; #define Ios ios::sync_with_stdio(false),cin.tie(0) #define mem(a,b) memset(a,b,sizeof a) #define int long long #define PII pair<int,int> #define pb push_back #define fi first #define se second #define endl '\n' /**/ const int N = 200010, mod = 1e9+7; int T, n, m; struct node{ int x, y, w; }a[N]; int ans, pre[N]; int sum; bool cmp(node a, node b){ return a.w < b.w; } int find(int x){ if(pre[x] != x) pre[x] = find(pre[x]); return pre[x]; } int kruskal() { sort(a+1, a+m+1, cmp); for(int i=1;i<=m;i++) { int r = i; while(r <= m && a[r].w == a[i].w) r++; r--; int cnt = 0; //记录可拿边的个数 for(int j=i;j<=r;j++) { int x = a[j].x, y = a[j].y, w = a[j].w; if(find(x) != find(y)) cnt++; //可拿边个数++ } for(int j=i;j<=r;j++) { int x = a[j].x, y = a[j].y, w = a[j].w; if(find(x) != find(y)) pre[find(x)] = find(y), sum += w, cnt --; //用掉了,cnt-- } i = r; if(cnt) return 0; //最后还剩余可拿边,最小生成树不唯一 } return 1; } signed main(){ Ios; cin>>T; while(T--) { cin>>n>>m; ans = 0, sum = 0; for(int i=1;i<=n;i++) pre[i] = i; for(int i=1;i<=m;i++) { int x, y, w;cin>>x>>y>>w; a[i] = {x, y, w}; } if(!kruskal()) cout<<"Not Unique!\n"; else cout << sum <<endl; } return 0; }
这种做法时间复杂度和求最小生成树复杂度相同,O(n+m)。
感觉比求次小生成树简单呢~ - 先遍历所有边,判断其是否可选,也就是判断其端点连接的两个连通块是否已经连通。如果没有连通,说明可选,删除的权值和
-
最小生成树的唯一性 (kruskral + 次小生成树)
2021-12-04 21:17:24给定一个带权无向图,如果是连通图,则至少存在一棵最小生成树,有时最小生成树并不唯一。...如果存在最小生成树,首先在第一行输出其总权重,第二行输出“Yes”,如果此树唯一,否则输出“No”。如...给定一个带权无向图,如果是连通图,则至少存在一棵最小生成树,有时最小生成树并不唯一。本题就要求你计算最小生成树的总权重,并且判断其是否唯一。
输入格式:
首先第一行给出两个整数:无向图中顶点数 N(≤500)和边数 M。随后 M 行,每行给出一条边的两个端点和权重,格式为“顶点1 顶点2 权重”,其中顶点从 1 到N 编号,权重为正整数。题目保证最小生成树的总权重不会超过 230。
输出格式:
如果存在最小生成树,首先在第一行输出其总权重,第二行输出“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
问题1:是否能生成最小生成树?
——>根据kruskral算法,若合并次数< n - 1次,则说明无法生成。
问题2:不能生成最小生成树情况下有多少个连通集合?
——>用一个map存一下祖宗节点,最后输出size即可。
问题3:如何判断最小生成树是否唯一?
——>去求次小生成树,次小生成树和最小生成树只有一边之差。
在求解最小生成树的过程中,我们用一个数组记录哪些边被用到了
对于没有用到的边,它连接的两个顶点称作a, b。我们把这条没被用过的边加入到最小生成树中,并删除原最小生成树连接a,b的边,其实就是结果减去原连接a,b两点的边的长度,再加上新加的这条边的长度,去判断一下两种情况下结果是否相等, 如果相等就说明最小生成树不唯一(因为用到的边不同)。
上代码!
#include<iostream> #include<algorithm> #include<unordered_map> #include<cstring> using namespace std; const int N = 510; unordered_map<int, int> fa; int n, m; int p[N]; struct Edge { int a, b, c; bool operator < (const Edge &w) const { return c < w.c; } }edge[N * N]; bool st[N]; //判断边是否被用到了 int g[N]; int find(int x)//并查集+路径压缩 { if(p[x] != x) p[x] = find(p[x]); return p[x]; } int main() { cin >> n >> m; for(int i = 0; i < m; i++) { int a, b, c; cin >> a >> b >> c; edge[i] = {a, b, c}; } sort(edge, edge + m); int cnt = 0; //记录合并次数 long long res = 0; //记录结果 for(int i = 1; i <= n; i++) p[i] = i; //并查集初始化 for(int i = 0; i < m; i++) { auto t = edge[i]; int x = find(t.a), y = find(t.b); if(x != y) //集合不一样就合并 { cnt++; //合并次数++ st[i] = true; //边被使用了 p[x] = y; //合并集合 res += t.c; g[t.a] = g[t.b] = t.c; //记录边长,为后面判断生成树是否唯一服务 } } if(cnt < n - 1) //合并次数 < n - 1说明不连通。(一开始1个点,一直加入加入...到n个点需要n - 1次) { for(int i = 1; i <= n; i++) { int t = find(i); if(!fa[t]) fa[t] = 1; //统计祖宗,放入map } cout << "No MST" << endl; cout << fa.size() << endl;//祖宗个数 return 0; } cout << res << endl; for(int i = 0; i < n; i++) { if(!st[i]) // 边没用过 { auto t = edge[i]; int a = t.a, b = t.b; //边连的两个点 if(res - g[a] + t.c == res) //结果相同则生成树不唯一 { puts("No"); return 0; } } } cout << "Yes" << endl; return 0; }
-
7-14 最小生成树的唯一性
2018-03-20 22:05:48给定一个带权无向图,如果是连通图,则至少存在一棵最小生成树,有时最小生成树并不唯一。本题就要求你计算最小生成树的总权重,并且判断其是否唯一。输入格式:首先第一行给出两个整数:无向图中顶点数 N(≤)...给定一个带权无向图,如果是连通图,则至少存在一棵最小生成树,有时最小生成树并不唯一。本题就要求你计算最小生成树的总权重,并且判断其是否唯一。
输入格式:
首先第一行给出两个整数:无向图中顶点数 N(≤)和边数 M。随后 M 行,每行给出一条边的两个端点和权重,格式为“顶点1 顶点2 权重”,其中顶点从 1 到N 编号,权重为正整数。题目保证最小生成树的总权重不会超过 230。
输出格式:
如果存在最小生成树,首先在第一行输出其总权重,第二行输出“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
思路:我们可能先判断连通性,由于结点数比较少,可以通过dfs直接判断连通块的个数,对于最小生成树的唯一性,我们可以通过求出次小生成的权值,在于最小生成树的权值进行比较即可。
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <algorithm> #include <set> #include <map> #include <cmath> using namespace std; const int maxn=550; int vis[maxn]; const long long int inf=0x3f3f3f3f3f3f3f; int G[maxn][maxn]; vector<int> v[maxn]; int fa[maxn]; long long int dis[maxn]; long long int pa[maxn][maxn]; bool used[maxn][maxn]; int n,m; void dfs(int x) { if(vis[x]) return ; vis[x]=1; for(int i=0; i<v[x].size(); i++) { dfs(v[x][i]); } } long long int prim(int x) { memset(fa,0,sizeof(fa)); memset(vis,0,sizeof(vis)); memset(pa,0,sizeof(pa)); memset(used,false,sizeof(used)); for(int i=1; i<=n; i++) { dis[i]=G[x][i]; fa[i]=x; } vis[x]=1; long long int ans=0; int cnt=0; int idx=x; for(int ka=1; ka<=n-1; ka++) { long long int maxx=inf; idx=0; for(int i=1; i<=n; i++) { if(!vis[i]&&dis[i]<maxx) { maxx=dis[i]; idx=i; } } ans+=dis[idx]; vis[idx]=1; used[idx][fa[idx]]=used[fa[idx]][idx]=1; for(int i=1; i<=n; i++) { if(vis[i]&&i!=idx ) { pa[idx][i]=pa[i][idx]=max(dis[idx],pa[i][fa[idx]]); } else { if(dis[i]>G[idx][i]) { fa[i]=idx; dis[i]=G[idx][i]; } } } } return ans; } long long int second_tree(long long int t) { long long int ans=inf; for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) { if(i!=j&&used[i][j]==0) ans=min(ans,t+G[i][j]-pa[i][j]); } } return ans; } int main() { cin>>n>>m; memset(vis,0,sizeof(vis)); memset(G,inf,sizeof(G)); for(int i=0; i<m; i++) { int x,y,d; cin>>x>>y>>d; G[x][y]=G[y][x]=d; v[x].push_back(y); v[y].push_back(x); } int cnt=0; for(int i=1; i<=n; i++) { if(vis[i]) continue; cnt++; dfs(i); } if(cnt>1) { cout<<"No MST"<<endl; cout<<cnt<<endl; return 0; } long long int tree=prim(1); long long int t2=second_tree(tree); cout<<tree<<endl; if(t2!=tree) cout<<"Yes"<<endl; else cout<<"No"<<endl; }
-
C语言-最小生成树
2019-04-22 22:27:12数据结构的最小生成树算法,对于求遍历和最短路径有参考意义,适合初学者,仅供分享 -
最小生成树的唯一性
2021-05-14 10:24:44进阶实验6-3.6 最小生成树的唯一性 (35 分) 给定一个带权无向图,如果是连通图,则至少存在一棵最小生成树,有时最小生成树并不唯一。本题就要求你计算最小生成树的总权重,并且判断其是否唯一。 输入格式: 首先... -
最小生成树的唯一性 (次小生成树)
2019-03-08 10:04:08给定一个带权无向图,如果是连通图,则至少存在一棵最小生成树,有时最小生成树并不唯一。本题就要求你计算最小生成树的总权重,并且判断其是否唯一。 输入格式: 首先第一行给出两个整数:无向图中顶点数N(≤500... -
7-6 最小生成树的唯一性 (35 分)(次小生成树)
2019-03-16 12:31:44给定一个带权无向图,如果是连通图,则至少存在一棵最小生成树,有时最小生成树并不唯一。本题就要求你计算最小生成树的总权重,并且判断其是否唯一。 输入格式: 首先第一行给出两个整数:无向图中顶点数 N(≤500... -
7-1 最小生成树的唯一性 (35 分)
2021-04-12 19:16:507-1 最小生成树的唯一性 (35 分) 给定一个带权无向图,如果是连通图,则至少存在一棵最小生成树,有时最小生成树并不唯一。本题就要求你计算最小生成树的总权重,并且判断其是否唯一。 输入格式: 首先第一行给出两... -
PTA 7-4 最小生成树的唯一性 (35分)
2020-05-28 12:03:50PTA 7-4 最小生成树的唯一性 (35分) 给定一个带权无向图,如果是连通图,则至少存在一棵最小生成树,有时最小生成树并不唯一。本题就要求你计算最小生成树的总权重,并且判断其是否唯一。 输入格式: 首先第一行给出... -
数据结构PTA习题:进阶实验6-3.6 最小生成树的唯一性 (35分)——最小生成树
2020-05-18 20:50:12进阶实验6-3.6 最小生成树的唯一性 (35分) 给定一个带权无向图,如果是连通图,则至少存在一棵最小生成树,有时最小生成树并不唯一。本题就要求你计算最小生成树的总权重,并且判断其是否唯一。 输入格式: 首先第一... -
最小生成树
2021-05-21 11:39:04一个连通图是生成树是图的极小连通子图,它包含图中的所有顶点,并且只含尽可能少的边。这意味着对于生成树来说,若砍去它的一条边,则会使生成树变成非连通图;...1)最小生成树不是唯一的,即最小 -
最小生成树两个常见算法
2020-09-13 10:30:22数据结构课程设计报告,最小生成树的算法实现,报告含有两个常见算法的源代码,并附有两个代码的详细思路说明,以及实现展示。 -
7-14 最小生成树的唯一性(30 分) 生成树综合练习题
2018-03-19 21:36:487-14 最小生成树的唯一性(30 分) 给定一个带权无向图,如果是连通图,则至少存在一棵最小生成树,有时最小生成树并不唯一。本题就要求你计算最小生成树的总权重,并且判断其是否唯一。 输入格式: 首先第... -
最小生成树MST详解
2021-08-24 15:55:30最小生成树(MST)是图的一个子集。本文将介绍两种常用的算法:Kruskal和Prim来寻找最小生成树。 -
Python之最小生成树 kruskal
2022-02-14 20:42:03蓝桥杯填空压轴考察了最小生成树 因此本文围绕算法kruskal解决最小生成树问题 适合小白阅读(会比较枯燥) 试题E: 抛开最小生成树,阅读完题目,我们知道,每两座城堡都有一座桥连接。 因此一共有C(2021,2)座... -
最小生成树——贪心算法
2019-03-19 21:25:59生成树和最小生成树1.1 问题的定义1.2 MST性质2.普里姆算法(Prim)2.1 算法流程2.2 算法正确性证明2.3 算法实现2.4 测试代码3.克鲁斯卡尔算法 1.生成树和最小生成树 1.1 问题的定义 一个连通图 的生成树是一个极小... -
最小生成树问题---Prim算法与Kruskal算法实现(MATLAB语言实现)
2021-04-18 04:47:132015-12-17晚,复习,甚是无聊,阅《复杂网络算法与应用》一书,得知最小生成树问题(Minimum spanning tree)问题。记之。何为树:连通且不含圈的图称为树。图T=(V,E),|V|=n,|E|=m,下列关于树的说法等价:T是一个树。... -
加权无向图与最小生成树(Prim算法和Kruskal算法)
2020-12-07 16:54:270 引入 通过加权无向图结合最小生成树相关算法,可以解决最小成本问题,并找到最小成本对应的顶点和边。 1 图的最小生成树定义及相关约定...(如果有权重相同的边,最小生成树可能就不唯一了) 2 最小生成树原理 2.1 性 -
Poj 1679 The Unique MST (最小生成树唯一性判定)
2013-03-08 22:08:31利用Prim算法求最小生成树,选择最小边时进行判断:是否有两个或以上的未选择顶点到已选顶点集合的权值相等的,若有则最小生成树不唯一。同时在松弛计算的时候也要 对刚加进的顶点进行权值是否相等的判断。 #... -
数据结构与算法—最小生成树(Prim算法和Kruskal算法算法详解)
2019-10-05 12:28:31在图论中,最小生成树也是一种常用算法,本文将从一些有趣的例子和来讲诉最小生成树的prim算法和kruskal算法。中间也夹杂了马克思主义理论,! -
图论——最小生成树
2017-09-24 20:42:08最小生成树 首先,生成树是建立在无向图中的,对于有向图,则没有生成树的概念,所以接...现在考虑带权图G,即图的边带权,则最小生成树就是在G中权值和最小的一颗生成树,显然最小生成树也不是唯一的,但是其权值唯一 -
最小生成树个数
2017-02-02 15:49:10在存在权值相等的边时,最小生成树可能有多个。话不多说,求它个数的方法如下:先用Prim生成最小树,同时记录边的关系。用并查集表示//不要压缩路径让每个元素都指向它的父亲节点。找出权值相同的边,去除树上的这条... -
POJ 1679 The Unique MST(算法导论23-1次优最小生成树)
2017-05-13 00:25:09最小生成树唯一性证明: 已知当前构造的边集A是最小生成树的子集。令无向图G的一个切割是,显然该切割是尊重A的。已知跨越该切割的轻量级边对于A是安全的,又因为该无向图G的每条边的权值都不相同,所以对于当前A而... -
图论——迪杰斯特拉算法和最小生成树
2021-02-01 08:20:10复习一下迪杰斯特拉算法,由于最小生成树的Prim算法与迪杰斯特拉算法极其类似,再顺便复习下最小生成树,顺便找两道水题验证代码正确性。 迪杰斯特拉算法 目的 该算法用于单源最短路,求一个图中,从起点S,到终点E... -
POJ 1679 The Unique MST (prim判断最小生成树是否唯一)
2017-09-01 23:31:30当更新加入c点时,若ac和bc的权值都为最小值,说明最小生成树不唯一。 理由很简单,当存在两个最小权值时,abc和acb都是最小生成树。 #include #include #include #include #include #include using namespace std... -
判断最小生成树的唯一性(POJ 1679 The Unique MST)
2018-01-16 11:04:31我们都知道,最小生成树(MST)是不唯一的,那么怎么才能判断最小生成树是否唯一呢? 首先来分析一下MST不唯一的原因; 举个题目中的样例2: 4 4 1 2 2 2 3 2 3 4 2 4 1 2 假设以上的边的编号为1 2 3 4 构造... -
进阶实验6-3.6 最小生成树的唯一性 (35分)
2020-03-07 08:18:03给定一个带权无向图,如果是连通图,则至少存在一棵最小生成树,有时最小生成树并不唯一。本题就要求你计算最小生成树的总权重,并且判断其是否唯一。 输入格式: 首先第一行给出两个整数:无向图中顶点数 N(≤500...