1. 程式人生 > >Codeforces 938D Buy a Ticket (轉化建圖 + 最短路)

Codeforces 938D Buy a Ticket (轉化建圖 + 最短路)

typedef ++ using fine return push 題意 aps stat

題目鏈接 Buy a Ticket

題意 給定一個無向圖。對於每個$i$ $\in$ $[1, n]$, 求$min\left\{2d(i,j) + a_{j}\right\}$

建立超級源點$n+1$, 對於每一條無向邊$(x, y, z)$,$x$向$y$連一條長度為$2z$的邊,反之亦然。

對於每個$a_{i}$, 從$i$到$n+1$連一條長度為$a_{i}$的邊,反之亦然。

然後跑一邊最短路即可。

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)
#define MP		make_pair
#define fi		first
#define se		second


typedef long long LL;

const int N = 2e5 + 10;

int n, m;
LL dis[N];

struct node{
	int u;
	LL w;
	friend bool operator < (const node &a, const node &b){
		return a.w > b.w;
	}
};

vector <node> v[N];

void dij(int s, LL dis[], vector <node> v[]){
	priority_queue <node> q;
	static bool vis[N];
	rep(i, 1, n) dis[i] = 1e18, vis[i] = false;
	q.push({s, 0});
	dis[s] = 0;
	while (!q.empty()){
		int u = q.top().u; q.pop();
		if (vis[u]) continue;
		vis[u] = 1;
		for (auto edge : v[u]) if (dis[u] + edge.w < dis[edge.u]){
			dis[edge.u] = dis[u] + edge.w;
			q.push({edge.u, dis[edge.u]});
		}
	}
}


int main(){

	scanf("%d%d", &n, &m);
	rep(i, 1, m){
		int x, y;
		LL z;
		scanf("%d%d%lld", &x, &y, &z);
		v[x].push_back({y, z * 2});
		v[y].push_back({x, z * 2});
	}

	rep(i, 1, n){
		LL x;
		scanf("%lld", &x);
		v[n + 1].push_back({i, x});
		v[i].push_back({n + 1, x});
	}

	dij(n + 1, dis, v);
	rep(i, 1, n) printf("%lld ", dis[i]);
	return 0;
}

  

Codeforces 938D Buy a Ticket (轉化建圖 + 最短路)