• 【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;
    }
    
  • 相关阅读:
    PUTTY与SecureCRT的比较
    java中volatile关键字的含义
    java中引用的原理
    Java陷阱之assert关键字
    脏读 幻读 不可重复读
    JAVA 的wait(), notify()与synchronized同步机制
    线程状态转换图
    并行、并发、同步和互斥
    B-树学习笔记
    平衡二叉树及其应用场景
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/51nod1443.html
Copyright © 2020-2023  润新知