P3366 【模板】最小生成树
链接:https://www.luogu.com.cn/problem/P3366
模板题:
kruskal代码:
核心是对边的排序,遍历,选择。
#include<iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<sstream>
#include<string>
#include<string.h>
#include<iomanip>
#include<stdlib.h>
#include<map>
#include<queue>
#include<limits.h>
#include<climits>
#include<fstream>
#include<stack>
typedef long long ll;
using namespace std;
const int N = 5e3 + 5, M = 2e5 + 1;
struct Edge { ll u, v, w; Edge() {}; }edge[M];
bool cmp(Edge a, Edge b) { return a.w < b.w; }
ll s[N];
ll find_set(ll x)
{
if (x != s[x])s[x] = find_set(s[x]);
return s[x];
}
ll n, m;
void kruskal()
{
sort(edge + 1, edge + m + 1, cmp);
for (int i = 1; i <= n; i++)s[i] = i;
ll ans = 0, cnt = 0;
for (int i = 1; i <= m; i++)
{
if (cnt == n - 1)break;
ll e1 = find_set(edge[i].u);
ll e2 = find_set(edge[i].v);
if (e1 == e2)continue;
else
{
s[e1] = e2;
ans += edge[i].w;
cnt++;
}
}
if (cnt == n - 1)cout << ans;
else cout << "orz";
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= m; i++)
{
cin >> edge[i].u >> edge[i].v >> edge[i].w;
}
kruskal();
return 0;
}
prim代码:
核心思路优先队列找点
#include<iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<sstream>
#include<string>
#include<string.h>
#include<iomanip>
#include<stdlib.h>
#include<map>
#include<queue>
#include<limits.h>
#include<climits>
#include<fstream>
#include<stack>
typedef long long ll;
using namespace std;
const int N = 5e3 + 5, M = 2e5 + 1;
struct edge
{
ll to, w;
edge(ll a, ll b) { to = a; w = b;}
};
vector<edge>G[M];
struct node
{
ll id, dis;//id:点,dis:边
node(ll a, ll b) { id = a, dis = b; }
bool operator <(const node& u)const {return dis > u.dis;}
};
ll n,m;
bool done[N];
void prim()
{
ll s = 1;//s:any point to begin
memset(done, 0, sizeof(done));
priority_queue<node>q;
q.push(node(s, 0));
ll ans = 0,cnt=0;
while (!q.empty())
{
node u = q.top(); q.pop();
if (done[u.id])continue;
done[u.id] = 1;
ans += u.dis;
cnt++;
for (edge i : G[u.id])
{
if (done[i.to])continue;
q.push(node(i.to, i.w));//下一个距离
}
}
if (cnt == n)cout << ans;//cnt:选取的点的个数
else cout << "orz";
}
int main()
{
ios::sync_with_stdio(false); cin.tie(0), cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= m; i++)
{
ll u, v, w; cin >> u >> v >> w;
G[u].push_back(edge(v, w)), G[v].push_back(edge(u, w));
}
prim();
return 0;
}