P3366 【模板】最小生成树

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;
}

对边进行排序,同时用并查集判断当前最小边的两个点是否已连通,未则加入更新,是则跳过

posted @ 2022-07-13 19:57  此间无物  阅读(28)  评论(0)    收藏  举报