P3110 [USACO14DEC]Piggy Back S TJ

题目链接

思路

这道题乍一看像是最短路,但又不知道从何下手。
考虑枚举每个节点,假设两个人到第 (i) 个节点相遇,剩下的路程一块走,那么我们很容易得出当前的能量为 (dis_{1~to~i} imes B + dis_{2~to~i} imes E + dis_{i~to~n} * P.)
那么我们可以预处理跑三遍最短路。
然后枚举每个节点寻找最优解。

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int MAXN = 4e4 + 10;
queue <int > s;
struct node {
	int next ,to;
}edge[MAXN << 1];
int head[MAXN] ,cnt = 0;
void add (int from ,int to) {
	edge[++ cnt].next = head[from];
	head[from] = cnt;
	edge[cnt].to = to;
}
int B ,E ,P ,n ,m;
int d[3][MAXN];
void bfs (int st) {
	int vis[MAXN] ,a[MAXN];
	memset (a ,-1 ,sizeof (a));
	s.push(st);
	a[st] = 0;
	while (! s.empty()) {
		int u = s.front();
		s.pop();
		for (int q = head[u];~ q;q = edge[q].next) {
			int v = edge[q].to;
			if (a[v] == -1) {
				a[v] = a[u] + 1;
				s.push(v);
			}
		}
	}
	if (st != n)
		for (int q = 1;q <= n;++ q)
			d[st][q] = a[q];
	else
		for (int q = 1;q <= n;++ q)
			d[0][q] = a[q];
	return ;
}
int ans = 0x3f3f3f3f;
int main () {
	memset (head ,-1 ,sizeof (head));
	scanf ("%d%d%d%d%d",&B ,&E ,&P ,&n ,&m);
	int from ,to;
	for (int q = 1;q <= m;++ q) {
		scanf ("%d%d",&from ,&to);
		add (from ,to) ,add (to ,from);
	}
	bfs (1); bfs (2); bfs (n);
	for (int q = 1;q <= n;++ q) {
		ans = min (ans ,d[1][q] * B + d[2][q] * E + d[0][q] * P);
	}
	printf ("%d
",ans);
	return 0;
}

cb
原文地址:https://www.cnblogs.com/tuscjaf/p/13881710.html