Codeforces 938D Buy a Ticket (转化建图 + 最短路)

题目链接  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;
}

  

原文地址:https://www.cnblogs.com/cxhscst2/p/8454662.html

时间: 2024-09-29 10:05:14

Codeforces 938D Buy a Ticket (转化建图 + 最短路)的相关文章

Codeforces 787D. Legacy 线段树优化建图+最短路

output standard output Rick and his co-workers have made a new radioactive formula and a lot of bad guys are after them. So Rick wants to give his legacy to Morty before bad guys catch them. There are n planets in their universe numbered from 1 to n.

Codeforces 938D Buy a Ticket

Buy a Ticket 题意要求:求出每个城市看演出的最小费用, 注意的一点就是车票要来回的. 题解:dijkstra 生成优先队列的时候直接将在本地城市看演出的费用放入队列里, 然后直接跑就好了,  dis数组存的是, 当前情况下的最小花费是多少. 代码: 1 #include<iostream> 2 #include<cstring> 3 #include<string> 4 #include<queue> 5 #include<vector&g

Codeforces 938D Buy a Ticket 【spfa优化】

用到了网络流的思想(大概).新建一个源点s,所有边权扩大两倍,然后所有的点向s连边权为点权的无向边,然后以s为起点跑spfa(S什么L优化的),这样每个点到s的距离就是答案. 原因的话,考虑答案应该是min(2*dis[i][j]+a[j]} ),那么每个点到s的距离就是若干条边边权的二倍加上某个点的点权,并且这个组合是最小的.证毕. #include<iostream> #include<cstdio> #include<queue> using namespace

最短路 || Codeforces 938D Buy a Ticket

题意:从城市u到v(双向)要花w钱,每个城市看演唱会要花不同的门票钱,求每个城市的人要看一场演唱会花费最少多少(可以在这个城市看,也可以坐车到别的城市看,然后再坐车回来) 思路:本来以为是多源..实际上是单源 考虑dij的松弛操作,是每次取队列里值最小的点u(队首),看它能拓展到的点v,如果经过u到v的代价比当前到v的代价低,那么就更新v 这里也同理,只不过代价是路程*2加上在v看演唱会的钱 嗯..神奇的dij #include <iostream> #include <cstdio&g

Codeforces 938 D. Buy a Ticket (dijkstra 求多元最短路)

题目链接:Buy a Ticket 题意: 给出n个点m条边,每个点每条边都有各自的权值,对于每个点i,求一个任意j,使得2×d[i][j] + a[j]最小. 题解: 这题其实就是要我们求任意两点的最短路,但是从点的个数上就知道这题不可以用floyd算法,其实多元最短路可以用dijkstra算.@.@!把所有的点的权值和点放到结构体里面,放入优先队列,其实这样就能保证每次拓展到的点就是这个点的最短路(因为是优先队列,保证拓展到的点这时候的值是最小的),其实就是这个点想通就很简单. 1 #inc

uva10067 Playing with Wheels 【建图+最短路】

题目:uva10067 Playing with Wheels 题意:给出一个机器,有四个循环的轮子,见图,然后给出一个初始数和目标数,然后期间不能出现的数字,每一分钟可以拨动一个数,问你最短需要的时间. 分析:这个题目可以转化为求图的最短路. 因为有对于一个当前状态,有8种可以转化为的状态,那么我们可以把每一种状态转化为一个点,然后状态之间连长度 1 的边,然后求一次初始状态到目标状态的最短路. 开始的时候我们每一组数据建图一次,下来0.9s,然后优化了一下,就是在每次建图不能到达的边删除之后

Hdu 5521 Meeting(建图+最短路)

题目地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=5521 思路:边数太多,不能直接建图.对于每个集合,设置一个虚拟点,对于每个集合中的点u:连一条u->S权值为0的边(点在集合中,花费为0):连一条S->u权值为w的边(从集合中一点到另一点花费w).分别计算从点1到i和从点n到i的最短路,枚举i,则ans=min( ans,max ( dist[0][i],dist[1][i] ) ). #include<queue> #i

【建图+最短路】Bzoj1001 狼抓兔子

Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: 左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路 1:(x,y)<==>(x+1,y) 2:(x,y)<==>(x,y+1) 3:(x,y)<==>(x+1,y+1) 道路上的权值表示这条路上最多能够通过的兔子数,道路是

poj2502题解(建图+最短路)

题意 给起点和终点的坐标,然后给出多条地铁每一站的坐标,每站地铁只能到相邻的地铁站,地铁的速度是40km/h,人行走的速度是10km/h,求起点到终点的最小时间(给出的坐标单位是m,最后求的时间单位是分钟) 解题思路 这题关键点在与建图,把图建好后跑dijkstra就很简单了,之前一直wa是想复杂了,以为要考虑起点和终点在地铁站的情况和不同线路的地铁站相交的情况,后来想不需要这么麻烦,同一条线路相邻的40,不同的10就可以了,相交的话,以10km/h走时间花费是0. AC代码 #include<