P3366 【模板】最小生成树
prim
#include <bits/stdc++.h>
using namespace std;
int n,m;
int dis[5001],vis[5001],cnt,pre,ans;
struct no2
{
int d,w;
};
struct no1
{
int v,d;
bool operator < (const no1 &x) const
{
return d > x.d;
}
};
vector <no2> e[5001];
void prim(int x)
{
memset(dis,0x3f,sizeof(dis));
priority_queue<no1> q;
dis[x] = 0;
pre = x;
q.push(no1{x,0});
do
{
pre = q.top().v;
q.pop();
if(vis[pre])continue;
vis[pre] = 1;
ans += dis[pre];
cnt++;
for (int i = 0; i < e[pre].size(); i++)
{
if(vis[e[pre][i].d] == 0 && dis[e[pre][i].d] > e[pre][i].w)
{
dis[e[pre][i].d] = e[pre][i].w;
q.push(no1{e[pre][i].d,dis[e[pre][i].d]});
}
}
}while(cnt < n && !q.empty());
if(cnt < n)
{
cout << "orz";
return ;
}
cout << ans;
}
int main()
{
cin >> n >> m;
int a,b,c;
for (int i = 1; i <= m ; i++)
{
cin >> a >> b >> c;
e[a].push_back(no2{b,c}),e[b].push_back(no2{a,c});
}
prim(1);
return 0;
}
和dijkstra很像,dis改为点离连通子图的最小距离,也就是边权,每次把最近的加入
kruskal
#include <bits/stdc++.h>
using namespace std;
int n,m;
int id[5001];
int ans;
int cnt;
struct node
{
int s,d,w;
}E[200001];
bool cmp(node x,node y)
{
return x.w < y.w;
}
int root(int x)
{
return id[x] == x ? x : id[x] = root(id[x]);
}
void mst()
{
for (int i = 1; i <= n; i++)id[i] = i;
for (int i = 1; i <= m; i++)
{
int ru = root(E[i].s);
int rv = root(E[i].d);
if(ru == rv)continue;//连通
ans += E[i].w;
id[ru] = rv;
cnt++;
if(cnt == n - 1)break;
}
for (int i = 2; i <= n; i++)
{
if(root(i) != root(i - 1))
{
cout << "orz";
return ;
}
}
cout << ans;
}
int main()
{
cin >> n >> m;
int a,b,c;
for (int i = 1; i <= m; i++)
{
cin >> a >> b >> c;
E[i] = node{a,b,c};
}
sort(E + 1, E + m + 1,cmp);
mst();
return 0;
}
对边进行排序,同时用并查集判断当前最小边的两个点是否已连通,未则加入更新,是则跳过
浙公网安备 33010602011771号