1. 程式人生 > 實用技巧 >【牛客7872 L】吃火鍋-超級源點跑單源最短路-浙江農林大學第十九屆程式設計競賽暨天梯賽選拔賽(同步賽)

【牛客7872 L】吃火鍋-超級源點跑單源最短路-浙江農林大學第十九屆程式設計競賽暨天梯賽選拔賽(同步賽)

【牛客7872 L】吃火鍋-超級源點跑單源最短路-浙江農林大學第十九屆程式設計競賽暨天梯賽選拔賽(同步賽)

傳送門

連結:https://ac.nowcoder.com/acm/contest/7872/L
來源:牛客網

題目描述

有n個城市,m條雙向道路。每條道路連線連線倆個城市,經過道路需要交路費。第i條路線可用於從城市vi到城市ui(以及從ui到vi),並且使用該路線需要花費wi。每個城市都開了一個相同的火鍋店,但是由於位置不同,每家火鍋店的價格不同,為了簡化問題。假設到第i個店吃的花費是val[i]。這個n個城市的人發現了這個漏洞,請你計算每個城市的人最少的吃火鍋花費(花費包括來回的路費和吃火鍋的費用,留在自己的城市不用路費)。

輸入描述:

輸出描述:

共一行。共n個數,第i個數代表第i個城市的人去吃火鍋的最小花費。

輸入

4 2
1 2 4
2 3 7
6 20 1 25

輸出

6 14 1 25

題意

n個點m條邊,每個點有家咖啡店,每個點的咖啡店的價格各不相同,對於當前處於 i 點的人來說,他可以選擇留在當前點喝咖啡,也可以選擇付出一些花費(來回路徑長度+去到的那個地方的咖啡價格)去另外一個地方喝咖啡。問每個點喝咖啡的最小花費?

題解

這道題目用到了一個非常巧妙也非常經典的技巧,那就是加一個超級源點
加一個超級源點,然後從超級源點向每個點建一條單向邊,邊權為該點咖啡價格,再把原先的邊權都變為原來的兩倍(來回路徑長度),然後以超級源點為起點跑單源最短路,求出來的超級源點到每個點的最短距離就是這個點喝咖啡的最小花費 。

/****************************
* Author : W.A.R            *
* Date : 2020-11-01-22:02   *
****************************/
/*
*/
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<stack>
#include<string>
#include<set>
#define IOS ios::sync_with_stdio(false)
#define show(x) std:: cerr << #x << " = " << x << std::endl;
#define mem(a,x) memset(a,x,sizeof(a))
#define Rint register int
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
const int maxm=2e6+10;
const ll mod=1e9+7;
const double PI=acos(-1.0);
const double eps=1e-7;
const ll inf=0x3f3f3f3f3f3f3f3f;
ll dis[maxn],a[maxn];
int head[maxn],ct;
struct Edge{int to,nxt;ll w;}e[maxn*2];
void addE(int u,int v,ll w){
	e[++ct].to=v;
	e[ct].w=w;
	e[ct].nxt=head[u];
	head[u]=ct;
}

struct node{
	int id;ll dis;
	bool operator < (const node a)const{
		return dis>a.dis;
	}
};

void dijkstra(){
	memset(dis,inf,sizeof(dis));
	dis[0]=0;
	priority_queue<node>q;
	q.push(node{0,0ll});
	while(!q.empty()){
		node now=q.top();q.pop();
		int u=now.id;
		ll ndis=now.dis;
		for(int i=head[u];i;i=e[i].nxt){
			int v=e[i].to;
			if(dis[u]+e[i].w<dis[v]){
				dis[v]=dis[u]+e[i].w;
				q.push(node{v,dis[v]});
			}
		}

	}
}

int main(){
	int n,m;scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++){
		int u,v;ll w;scanf("%d%d%lld",&u,&v,&w);
		addE(u,v,2*w);addE(v,u,2*w);
	}
	for(int i=1;i<=n;i++)scanf("%lld",&a[i]),addE(0,i,a[i]);
	dijkstra();
	for(int i=1;i<=n;i++)printf("%lld%c",dis[i],i==n?'\n':' ');
}