CodeForces - 938D Buy a Ticket [Dijkstra]

xiaoxiao2021-02-28  48

题意:给一张图,每个点有一个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"); }

转载请注明原文地址: https://www.6miu.com/read-2623541.html

最新回复(0)