最小生成树 Problem C: 畅通工程

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

  • 思路 1: Prim 中加入一个numV变量记录加入最小生成树的节点个数,如果最后个数比总顶点数少则输出-1,否则输出ans

【注意】:多点测试,每轮结束要手动清空G[maxn]

#include <bits/stdc++.h>
using namespace std;
const int maxn = 110, INF = 0x3fffffff;
int d[maxn];
bool vis[maxn];
struct node
{
    int nex, dis;
};
vector<node> G[maxn];
struct tmp_node
{
    int id, d;
    bool operator < (const tmp_node & tmp) const { return d > tmp.d; }
};
int Prim(int start, int n)
{
    fill(d, d + n + 1, INF);
    memset(vis, false, sizeof(vis));
    d[start] = 0;
    int ans = 0; int numV = 0; //记录加入最小树的顶点数!
    priority_queue<tmp_node> pq;
    pq.push(tmp_node{start, 0});
    while(!pq.empty())
    {
        tmp_node now = pq.top();
        pq.pop();
        if(vis[now.id]) continue;
        vis[now.id] = true;
        ans += d[now.id];
        numV++;
        for(int i = 0; i < G[now.id].size(); ++i)
        {
            int nex = G[now.id][i].nex;
            int len = G[now.id][i].dis;
            if(vis[nex] == false && len < d[nex])
            {
                d[nex] = len;
                pq.push(tmp_node{nex, d[nex]});
            }
        }
    }
    if(numV < n) return -1;
    else return ans;
}
int main()
{
    int ne, nv;
    while(scanf("%d %d", &ne, &nv) != EOF && ne != 0)
    {
        for(int i = 0; i < ne; ++i)
        {
            int c1, c2, len;
            scanf("%d %d %d", &c1, &c2, &len);
            G[c1].push_back(node{c2, len});
            G[c2].push_back(node{c1, len});
        }
        int cost = Prim(1, nv);
        if(cost == -1) printf("?\n");
        else printf("%d\n", cost);
        for(int i = 1; i <= nv; ++i) G[i].clear();
    }
}

  • 思路 2:Kruskal
#include <bits/stdc++.h>
using namespace std;
struct edge
{
    int v1, v2, len;
    bool operator < (const edge & tmp) const { return len > tmp.len; }
};
int FindRoot(int x, vector<int> & f)
{
    int tmp = x;
    while(f[x] != x)
    {
        x = f[x];
    }
    while(f[tmp] != tmp)
    {
        int tmp2 = tmp;
        tmp = f[tmp];
        f[tmp2] = x;
    }
    return x;
}
int Kruskal(int nv, priority_queue<edge> & pq)
{
    vector<int> father(nv);
    for(int i = 0; i < nv + 1; ++i) father[i] = i;
    int ans = 0, numE = 0;
    while(!pq.empty())
    {
        edge now = pq.top();
        pq.pop();
        int ra = FindRoot(now.v1, father), rb = FindRoot(now.v2, father);
        if(ra != rb)
        {
            father[ra] = rb;
            ans += now.len;
            numE++;
            if(numE >= nv-1) break;
        }
    }
    if(numE != nv-1) return -1;
    else return ans;
}
int main()
{
    int ne, nv;
    while(scanf("%d %d", &ne, &nv) != EOF && ne != 0)
    {
        priority_queue<edge> ans;
        for(int i = 0; i < ne; ++i)
        {
            int c1, c2, len;
            scanf("%d %d %d", &c1, &c2, &len);
            ans.push(edge{c1, c2, len});
        }
        int cost = Kruskal(nv, ans);
        if(cost == -1) printf("?\n");
        else printf("%d\n", cost);
    }
    return 0;
}

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

猜你喜欢

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