Prim堆优化

好久没写博客了,想坚持下来真是挺不容易的呢,这段时间没做什么呢,从今天起继续写博客,加油奋斗,为今年区域赛好好准备,以前一直不太明白prim怎么堆优化,今天终于想明白了。

#1109 : 最小生成树三·堆优化的Prim算法

时间限制: 10000ms
单点时限: 1000ms
内存限制: 256MB
描述

回到两个星期之前,在成功的使用Kruscal算法解决了问题之后,小Ho产生了一个疑问,究竟这样的算法在稀疏图上比Prim优化之处在哪里呢?

提示:没有无缘无故的优化!
输入

每个测试点(输入文件)有且仅有一组测试数据。

在一组测试数据中:

第1行为2个整数N、M,表示小Hi拥有的城市数量和小Hi筛选出路线的条数。

接下来的M行,每行描述一条路线,其中第i行为3个整数N1_i, N2_i, V_i,分别表示这条路线的两个端点和在这条路线上建造道路的费用。

对于100%的数据,满足N<=10^5, M<=10^6,于任意i满足1<=N1_i, N2_i<=N, N1_i≠N2_i, 1<=V_i<=10^3.

对于100%的数据,满足一定存在一种方案,使得任意两座城市都可以互相到达。

输出

对于每组测试数据,输出1个整数Ans,表示为了使任意两座城市都可以通过所建造的道路互相到达至少需要的建造费用。

样例输入
5 29
1 2 674
2 3 249
3 4 672
4 5 933
1 2 788
3 4 147
2 4 504
3 4 38
1 3 65
3 5 6
1 5 865
1 3 590
1 4 682
2 4 227
2 4 636
1 4 312
1 3 143
2 5 158
2 3 516
3 5 102
1 5 605
1 4 99
4 5 224
2 4 198
3 5 894
1 5 845
3 4 7
2 4 14
1 4 185
样例输出
92
#include <iostream>      
#include <cstdio>      
#include <map>
#include <queue>  
#include <cstring>      
#include <cmath>      
#include <vector>      
#include <algorithm> 
#define rep(i,a,b) for(int i = a; i < b;i++)            
using namespace std;
typedef long long LL;
const int maxm = 1e6 + 10;
const int maxn = 1e5 + 10;
const int inf = 0x3f3f3f3f;
struct Edge
{
	int to,next,w;
	Edge(int to =0,int next =-1,int w=0):to(to),next(next),w(w){}
	bool operator <(const Edge &rhs)const{
		return w > rhs.w;
	}
};
Edge edges[maxm<<1];
int head[maxn];
bool inq[maxn];
void AddEdge(int u,int v,int w,int &tot)
{
	edges[tot].next = head[u];
	edges[tot].w = w;
	edges[tot].to = v;
	head[u] = tot++;
}
void pushEdge(priority_queue<Edge>&q,int v)
{
	for(int e = head[v]; e != -1; e=edges[e].next)q.push(edges[e]);
}
int Prim(int n)
{
	priority_queue<Edge>q;
	memset(inq,0,sizeof inq);
	pushEdge(q,0);
	inq[0] = true;
	int vs = n-1;
	int ans = 0;
	while(vs) {
		Edge e = q.top();q.pop();
		while(inq[e.to]){
			e = q.top();q.pop();
		}
		ans += e.w;
		inq[e.to] = true;
		pushEdge(q,e.to);
		vs--;
	}  
	return ans;
}
int main(){
	int n,m,tot;
	while(~scanf("%d%d", &n,&m)) {
		rep(i,0,n)head[i] = -1;
		tot = 0;
		while(m--) {
			int u,v,w;
			scanf("%d%d%d",&u,&v,&w);
			u--;
			v--;
			AddEdge(u,v,w,tot);
			AddEdge(v,u,w,tot);
		}
		printf("%d\n", Prim(n));
	}
    return 0;
}




  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值