CodeForces - 938D Buy a Ticket [Dijkstra]

题意:给一张图,每个点有一个weight,每一条边有一个weight,定义一个点到到另一个点的value是,2*dist(i,j)+weight[j],求每一个点的最小weight。

题解:我们可以把所有点当成起点,加入优先队列中跑,并且每个点的初始值为weight[i],然后跑Dijkstra,得到的所有答案,就是以每一个点为起点到其他点的最小值。

一开始我想通过将点分为两类,起点和终点,然后把起点的一半变为终点,终点的一半变为起点,然后跑logn遍dij,所以复杂度是O(logn*logn*n)的复杂度,但是TLE了,但是这种方法主要用于点到自己的距离不影响答案的时候使用,这道题不影响所以可以直接将所有点放入队列中。

注意:spfa在这里复杂度有点迷,一直过不去。

AC代码:

#include<stdio.h>
#include<vector>
#include<queue>
#define inf 2000000000000000000ll
using namespace std;
typedef long long ll;
struct node
{
	ll to,w;
	node(){}
	node(ll to,ll w)
	{
		this->to=to;
		this->w=w;
	}
};
vector<node>vt[200005];
ll a[200005],dist[200005],mark[200005],n,m;
priority_queue<node>que;
bool operator<(node a,node b)
{
	return a.w>b.w;
}
void dij()
{
	for(ll i=1;i<=n;i++)
		dist[i]=a[i],mark[i]=0,que.push(node(i,dist[i]));
	while(!que.empty())
	{
		node k=que.top();
		que.pop();
		if(mark[k.to])continue;
		mark[k.to]=1;
		for(int i=0;i<vt[k.to].size();i++)
		{
			int to=vt[k.to][i].to;
			if(mark[to]==0&&dist[to]>k.w+vt[k.to][i].w)
			{
				dist[to]=k.w+vt[k.to][i].w;
				que.push(node(to,dist[to]));
			}
		}
	}
}

int main()
{
	scanf("%lld%lld",&n,&m);
	for(ll i=0;i<m;i++)
	{
		ll u,v,w;
		scanf("%lld%lld%lld",&u,&v,&w);
		vt[u].push_back(node(v,w*2));
		vt[v].push_back(node(u,w*2));
	}
	for(ll i=1;i<=n;i++)
		scanf("%lld",&a[i]);
	dij();
	for(ll i=1;i<=n;i++)
		printf("%lld ",dist[i]);
	printf("\n");
}

    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/acterminate/article/details/79334893
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞