1. 程式人生 > 實用技巧 >[kuangbin]專題六 最小生成樹 題解+總結

[kuangbin]專題六 最小生成樹 題解+總結

kuangbin專題連結:https://vjudge.net/article/752

kuangbin專題十二 基礎DP1 題解+總結:https://www.cnblogs.com/RioTian/p/13110438.html

最小生成演算法 介紹模板

總結:

文章目錄

目錄

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

原題連結:傳送門

思路:

  1. 完完全全的模板題,按照最小生成樹的思想寫程式碼即可。

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.暢通工程再續

原題連結:傳送門

思路: