最小生成树 Problem A: 还是畅通工程

>>>>>题目地址<<<<<<

【注】codeup不是单点测试!!!

  • 思路1: Prim算法
#include <bits/stdc++.h>
using namespace std;
const int maxn = 110, INF = 0x3fffffff;
int d[maxn], G[maxn][maxn];
bool vis[maxn];
int Prim(int start, int n)
{
    fill(d, d + maxn, INF);
    memset(vis, false, sizeof(vis));
    d[start] = 0;
    int ans = 0;
    for(int i = 0; i < n; ++i)
    {
        int mid = -1, Min = INF;
        for(int j = 1; j <= n; ++j)
        {
            if(vis[j] == false && d[j] < Min)
            {
                Min = d[j];
                mid = j;
            }
        }
        if(mid == -1) return -1;
        vis[mid] = true;
        ans += d[mid];
        for(int j = 1; j <= n; ++j)
        {
            if(vis[j] == false && G[mid][j] < d[j])
            {
                d[j] = G[mid][j];
            }
        }
    }
    return ans;
}
int main()
{
    int n;
    while(scanf("%d", &n) != EOF)
    {
        if(n == 0) break;
        int N = n * (n - 1) / 2;
        fill(G[0], G[0] + maxn * maxn, INF);
        for(int i = 0; i < N; ++i)
        {
            int c1, c2, len;
            scanf("%d %d %d", &c1, &c2, &len);
            G[c1][c2] = G[c2][c1] = len;
        }
        printf("%d\n", Prim(1, n));
    }
    return 0;
}
  • 思路2: Prim+堆优化
#include <bits/stdc++.h>
using namespace std;
const int maxn = 110, INF = 0x3fffffff;
int d[maxn], G[maxn][maxn];
bool vis[maxn];
struct node
{
    int id, d;
    bool operator < (const node & tmp) const { return d > tmp.d; }
};
int Prim(int start, int n)
{
    fill(d, d + maxn, INF);
    memset(vis, false, sizeof(vis));
    d[start] = 0;
    priority_queue<node> q;
    q.push(node{start, 0});
    int ans = 0;
    while(!q.empty())
    {
        node now = q.top();
        q.pop();
        if(vis[now.id]) continue;
        vis[now.id] = true;
        ans += d[now.id];
        for(int i = 1; i <= n; ++i)
        {
            if(vis[i] == false && G[now.id][i] != INF)
            {
                if(G[now.id][i] < d[i])
                {
                    d[i] = G[now.id][i];
                    q.push(node{i, d[i]});
                }
            }
        }
    }
    return ans;
}
int main()
{
    int n;
    while(scanf("%d", &n) != EOF)
    {
        if(n == 0) break;
        int N = n * (n - 1) / 2;
        fill(G[0], G[0] + maxn * maxn, INF);
        for(int i = 0; i < N; ++i)
        {
            int c1, c2, len;
            scanf("%d %d %d", &c1, &c2, &len);
            G[c1][c2] = G[c2][c1] = len;
        }
        printf("%d\n", Prim(1, n));
    }
    return 0;
}

  • 思路3: Kruskal
#include <bits/stdc++.h>
using namespace std;
const int maxn = 110;
struct edge
{
    int v1, v2, len;
};
int father[maxn];
void Init(int n) { for(int i = 0; i <= maxn; ++i) father[i] = i;}
int FindRoot(int x)
{
    int tmp = x;
    while(father[x] != x)
    {
        x = father[x];
    }
    while(father[tmp] != tmp)
    {
        int tmp2 = tmp;
        tmp = father[tmp];
        father[tmp2] = x;
    }
    return x;
}
bool cmp(edge a, edge b) { return a.len < b.len; }
int Kruskal(int nv, int ne, vector<edge> & ans)
{
    Init(nv);
    int sum = 0, numE = 0;
    sort(ans.begin(), ans.end(), cmp);
    for(int i = 0; i < ne; ++i)
    {
        int ra = FindRoot(ans[i].v1), rb = FindRoot(ans[i].v2);
        if(ra != rb)
        {
            father[ra] = rb;
            sum += ans[i].len;
            numE++;
            if(numE == nv-1) break;
        }
    }
    if(numE != nv-1) return -1;
    else return sum;
}

int main()
{
    int n;
    while(scanf("%d", &n) != EOF)
    {
        if(n == 0) break;
        int N = n * (n - 1) / 2;
        vector<edge> ans;
        for(int i = 0; i < N; ++i)
        {
            int c1, c2, len;
            scanf("%d %d %d", &c1, &c2, &len);
            ans.push_back(edge{c1, c2, len});
        }
        printf("%d\n", Kruskal(n, N, ans));
    }
    return 0;
}

  • 思路 4 Kruskal + 堆优化 这题属于边稠密图,正常sort的话可能会超时, 故用堆优化
#include <bits/stdc++.h>
using namespace std;
const int maxn = 110;
struct edge
{
    int v1, v2, len;
    bool operator < (const edge & tmp) const { return len > tmp.len; }
};
int father[maxn];
void Init(int n) { for(int i = 0; i <= maxn; ++i) father[i] = i;}
int FindRoot(int x)
{
    int tmp = x;
    while(father[x] != x)
    {
        x = father[x];
    }
    while(father[tmp] != tmp)
    {
        int tmp2 = tmp;
        tmp = father[tmp];
        father[tmp2] = x;
    }
    return x;
}
int Kruskal(int nv, int ne, priority_queue<edge> & pq)
{
    Init(nv);
    int sum = 0, numE = 0;
    while(!pq.empty())
    {
        edge now = pq.top();
        pq.pop();
        int ra = FindRoot(now.v1), rb = FindRoot(now.v2);
        if(ra != rb)
        {
            numE++;
            sum += now.len;
            father[ra] = rb;
            if(numE == nv-1) break;
        }
    }
    if(numE != nv-1) return -1;
    else return sum;
}

int main()
{
    int n;
    while(scanf("%d", &n) != EOF)
    {
        if(n == 0) break;
        int N = n * (n - 1) / 2;
        priority_queue<edge> q;
        for(int i = 0; i < N; ++i)
        {
            int c1, c2, len;
            scanf("%d %d %d", &c1, &c2, &len);
            q.push(edge{c1, c2, len});
        }
        printf("%d\n", Kruskal(n, N, q));
    }
    return 0;
}

发布了316 篇原创文章 · 获赞 5 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_42347617/article/details/104852043