【51nod1443】路径和树(堆优化dijkstra乱搞)

点此看题面

大致题意:给你一个无向联通图,要求你求出这张图中从u开始的权值和最小最短路径树的权值之和。

最短路径树:从u开始到任意点的最短路径与在原图中相比不变)

既然要求最短路径,那么最容易想到的就是dijkstra和SPFA(毕竟Floyd的时间复杂度难以承受),又由于黄学长说能用dijkstra时尽量用dijkstra,所以,我就打了一个堆优化的dijkstra开始乱搞

其实,这道题目的思路真的挺简单的,只要朴素地做一遍dijkstra,并在更新距离的过程中同时更新这个最短距离是从哪一条边得到的,就可以轻松求出这张图的最短路径树了。

代码如下:

#include<bits/stdc++.h>
#define LL long long
#define N 300000
#define M 300000
using namespace std;
int n,m,u,ee=0,lnk[N+5]={0},vis[N+5]={0};
LL ans,used[N+5]={0},MIN[N+5]={0};
struct edge
{
	int to,nxt;
	LL val;
}e[2*M+5];
typedef pair<LL,int> Pr;
priority_queue<Pr,vector<Pr>,greater<Pr> > q;//用优先队列(即堆)来优化dijkstra 
void add(int x,int y,int z) 
{
	e[++ee].to=y,e[ee].nxt=lnk[x],e[ee].val=z,lnk[x]=ee;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1,x,y,z;i<=m;i++) 
		scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z);
	scanf("%d",&u);
	q.push(make_pair(0,u));//初始化,将u点放入堆中 
	while(!q.empty())
	{
		int k=q.top().second;q.pop();
		if(vis[k]) continue;else vis[k]=1;//判断该点是否被访问过 
		for(int i=lnk[k];i;i=e[i].nxt) 
			if(!vis[e[i].to]&&(!MIN[e[i].to]||MIN[k]+e[i].val<MIN[e[i].to]||(MIN[k]+e[i].val==MIN[e[i].to]&&e[i].val<used[e[i].to]))) ans-=used[e[i].to]-e[i].val,MIN[e[i].to]=MIN[k]+(used[e[i].to]=e[i].val),q.push(make_pair(MIN[e[i].to],e[i].to));//一个麻烦的更新过程,同时更新最短路和最短路从哪一条边得来,并同时更新ans	
	}
	return printf("%lld",ans),0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值