Title

(模板)最小生成树(Prim)

(模板)最小生成树(Prim)

题目描述

如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 orz

输入格式

第一行包含两个整数 \(N,M\),表示该图共有 \(N\) 个结点和 \(M\) 条无向边。

接下来 \(M\) 行每行包含三个整数 \(X_i,Y_i,Z_i\),表示有一条长度为 \(Z_i\) 的无向边连接结点 \(X_i,Y_i\)

输出格式

如果该图连通,则输出一个整数表示最小生成树的各边的长度之和。如果该图不连通则输出 orz

样例 #1

样例输入 #1

4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3

样例输出 #1

7

提示

数据规模:

对于 \(20\%\) 的数据,\(N\le 5\)\(M\le 20\)

对于 \(40\%\) 的数据,\(N\le 50\)\(M\le 2500\)

对于 \(70\%\) 的数据,\(N\le 500\)\(M\le 10^4\)

对于 \(100\%\) 的数据:\(1\le N\le 5000\)\(1\le M\le 2\times 10^5\)\(1\le Z_i \le 10^4\)

样例解释:

所以最小生成树的总边权为 \(2+2+3=7\)

代码

神奇的代码
#include <bits/stdc++.h>
#define endl '\n'

int head[5050];
bool vis[5050];
int dis[5050];
int cnt = 0;
const int inf = 0x7f7f7f7f;
struct Edge
{
    int u, v, w;
    int nxt;
}edge[400010];

void AddEdge(int u, int v, int w)
{
    edge[++cnt].u = u;
    edge[cnt].v = v;
    edge[cnt].w = w;
    edge[cnt].nxt = head[u];
    head[u] = cnt;
}

struct Node
{
    int dest;
    int weight;
    bool operator < (const Node &tmp) const
    {
        return weight > tmp.weight;
    }
    Node (int dest, int weight) : dest(dest), weight(weight) {}
};

std::priority_queue<Node> que;

void prim(int n)
{
    dis[1] = 0;
    que.push({1, 0});
    int ans = 0, tot = 0;
    while(!que.empty())
    {
        Node t = que.top();
        int u = t.dest, w = t.weight;
        que.pop();
        if (vis[u]) continue;
        vis[u] = 1;
        ans += w;
        tot++;
        for (int i = head[u]; i != -1; i = edge[i].nxt)
        {
            if (dis[edge[i].v] > edge[i].w)
            {
                dis[edge[i].v] =  edge[i].w;
                que.push({edge[i].v, edge[i].w});
            }
        }
    }
    if (tot == n)
    {
        std::cout << ans << endl;
    }
    else
    {
        std::cout << "orz" << endl;
    }
}

int main()
{
    //freopen("in.txt", "r", stdin);
    std::fill(head, head + 5050, -1);
    std::fill(vis, vis + 5050, 0);
    std::fill(dis, dis + 5050, inf);
    int n = 0, m = 0;
    std::cin >> n >> m;
    int u = 0, v = 0, w = 0;
    for (int i = 1; i <= m; i++)
    {
        std::cin >> u >> v >> w;
        AddEdge(u, v, w);
        AddEdge(v, u, w);
    }
    prim(n);
    return 0;
}

posted @ 2024-10-06 11:21  栗悟饭与龟功気波  阅读(21)  评论(0)    收藏  举报