[kuangbin]專題六 最小生成樹 題解+總結
阿新 • • 發佈:2020-07-27
kuangbin
專題連結:https://vjudge.net/article/752
kuangbin
專題十二 基礎DP1 題解+總結:https://www.cnblogs.com/RioTian/p/13110438.html
總結:
文章目錄
目錄
- 總結:
- 1.Jungle Roads
- Networking
- 3.Constructing Roads
- 4.Agri-Net
- 5.The Unique MST
- 6.Highways
- 7.Arctic Network
- 8.Building a Space Station
- 9.還是暢通工程
- 10.暢通工程再續
1.Jungle Roads
原題連結:傳送門
題意:
N個頂點的無向圖,給你每條邊的長度,要你求該圖的最小生成樹.其中每個點用大寫字母A-Z表示.
思路:
直接kruskal
模板即可,轉換輸入格式.注意輸入中的邊沒有重複邊,所以無需判重.
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=30; const int maxm=100+10; struct Edge { int u,v,dist; Edge(){} Edge(int u,int v,int d):u(u),v(v),dist(d){} bool operator<(const Edge &rhs)const { return dist<rhs.dist; } }; struct Kruskal { int n,m; Edge edges[maxm]; int fa[maxn]; int findset(int x){ return fa[x]==-1?x:fa[x]=findset(fa[x]); } void init(int n) { this->n=n; m=0; memset(fa,-1,sizeof(fa)); } void AddEdge(int u,int v,int dist) { edges[m++]=Edge(u,v,dist); } int kruskal() { int sum=0,cnt=0; sort(edges,edges+m); for(int i=0;i<m;i++) { int u=edges[i].u, v=edges[i].v; if(findset(u) != findset(v)) { sum +=edges[i].dist; fa[findset(u)] = findset(v); if(++cnt>=n-1) return sum; } } return -1; } }KK; int main() { int n; while(scanf("%d",&n)==1&&n) { KK.init(n); for(int i=0;i<n-1;i++) { char s1[10],s2[10]; int k,v,d; scanf("%s%d",s1,&k); while(k--) { scanf("%s%d",s2,&d); v=s2[0]-'A'; KK.AddEdge(i,v,d); } } printf("%d\n",KK.kruskal()); } return 0; }
Networking
原題連結:傳送門
思路:
- 完完全全的模板題,按照最小生成樹的思想寫程式碼即可。
prim 演算法
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; #define ms(a,b) memset(a,b,sizeof a); const int N = 55; int n, m; int g[N][N], d[N]; bool book[N]; int prime() { ms(d, 0x3f); ms(book, false); int ans = 0; //有點類似最短路的dijstra演算法 for (int i = 0; i < n; ++i) { int t = -1; for (int j = 1; j <= n; ++j) { if (!book[j] && (t == -1 || d[t] > d[j])) t = j; } book[t] = true;//加入集合 if (i) ans += d[t];//代表不是第一個點 //改變其他點到該集合的距離 for (int j = 1; j <= n; ++j)d[j] = min(d[j], g[t][j]); } return ans; } int main() { //freopen("in.txt", "r", stdin); while (cin >> n && n) { cin >> m; //if (m == 0) { cout << 0 << endl; continue; } ms(g, 0x3f); int u, v, w; for (int i = 1; i <= m; ++i) { cin >> u >> v >> w; g[v][u] = g[u][v] = min(g[v][u], w);//重邊,選擇最小值 } cout << prime() << endl; } return 0; }
kruskal演算法
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define ms(a,b) memset(a,b,sizeof a);
const int maxn = 200 + 55;
const int maxm = 1e5 + 5;
struct edge {
int from, to;
int cost;
}b[maxm];
int n, m;
int f[maxn];
bool cmp(edge a, edge b) {
return a.cost < b.cost;
}
int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); }
int kruskal() {
int u, v;
int ans = 0, total = 0;
for (int i = 1; i <= m; ++i) {
u = find(b[i].from);
v = find(b[i].to);
if (u != v) {
ans += b[i].cost;
f[u] = v;
++total;
if (total == n - 1)
return ans;
}
}
return 0;
}
int main() {
//freopen("in.txt", "r", stdin);
int u, v, w;
while (cin >> n && n) {
cin >> m;
for (int i = 0; i <= n; ++i)f[i] = i;
for (int i = 1; i <= m; ++i) {
cin >> b[i].from >> b[i].to >> b[i].cost;
}
sort(b + 1, b + 1 + m,cmp);
cout << kruskal() << endl;
}
return 0;
}
3.Constructing Roads
原題連結:傳送門
思路:
4.Agri-Net
原題連結:傳送門
思路:
5.The Unique MST
原題連結:傳送門
思路:
6.Highways
原題連結:傳送門
思路:
7.Arctic Network
原題連結:傳送門
思路:
8.Building a Space Station
原題連結:傳送門
思路:
9.還是暢通工程
原題連結:傳送門
思路:
10.暢通工程再續
原題連結:傳送門
思路: