[Usaco2014 Dec]Piggy Back

Description

给定一个N个点M条边的无向图,其中Bessie在1号点,Elsie在2号点,它们的目的地为N号点。Bessie每经过一条边
需要消耗B点能量,Elsie每经过一条边需要消耗E点能量。当它们相遇时,它们可以一起行走,此时它们每经过一
条边需要消耗P点能量。求它们两个到达N号点时最少消耗多少能量?

Input

The first line of input contains the positive integers B, E, P, N, and M.
All of these are at most 40,000. B, E, and P are described above.
N is the number of fields in the farm (numbered 1…N, where N >= 3),
and M is the number of connections between fields.
Bessie and Elsie start in fields 1 and 2, respectively.
The barn resides in field N.
The next M lines in the input each describe a connection between a pair of different fields,
specified by the integer indices of the two fields. Connections are bi-directional.
It is always possible to travel from field 1 to field N, and field 2 to field N, along a series of such connections.

Output

A single integer specifying the minimum amount of energy Bessie and
Elsie collectively need to spend to reach the barn. In the example
shown here, Bessie travels from 1 to 4 and Elsie travels from 2 to 3
to 4. Then, they travel together from 4 to 7 to 8.
Sample Input
4 4 5 8 8
1 4
2 3
3 4
4 7
2 5
5 6
6 8
7 8

Sample Output

22

题目翻译

输入
第一行输入包含正整数B,E,P,N和M。
所有这些都是最多40,000。B,E和P如上所述。
N是服务器场中的字段数(编号为1…N,其中N> = 3)。
M是字段之间的连接数。
Bessie和Elsie分别从第1和第2领域开始。
谷仓位于字段N中。
输入中的下一个M行描述了由两个字段的整数索引指定的一对不同字段之间的连接。连接是双向的。
始终可以沿着一系列这样的连接从场1到场N,场2到场N.
输出
一个整数,指定Bessie和
Elsie共同需要花费的最小能量来到谷仓。在
这里显示的例子中,Bessie从1到4旅行,Elsie从2到3
到4旅行。然后,他们一起旅行从4到7到8

题解:
既然题目已经给出了3个出发点,那么最简便的方法就是,以这三个点为出发点,分别做三次spfa求出每个点到这三个点的最短路径,最后做一遍循环,去搜索若以当前点为交汇点所花费的权值为多少即可。

代码如下:

#include<bits/stdc++.h>
using namespace std;
int v[4000000],flog[400010],x[400010],y[400010],z[401000];
int dp[400010],now[400100],son[400100],pre[401000],f[400010][4];
bool k[400010];
int n,m,sum,t;
void tot(int a,int b,int  c) {
	pre[++sum]=now[a];
	now[a]=sum;
	son[sum]=b;
	dp[sum]=c;
}//每个点所连接的点
void spfa() {
	memset(flog,63,sizeof(flog));//预处理
	memset(k,false,sizeof(k));//预处理
	int head=0,tail=1;
	flog[t]=0;
	v[1]=t;
	while(head<tail) {
		int f=v[++head];
		k[f]=false;
		for(int i=now[f]; i; i=pre[i]) {
			int h=son[i];
			if(flog[f]+dp[i]<flog[h]) {
				flog[h]=flog[f]+dp[i];
				if(!k[h]) {
					v[++tail]=h;
					k[h]=true;
				}
			}
		}

	}
}//spaf求最短路径
int main() {
	int B,E,P,maxx=1e9;
	scanf("%d%d%d%d%d",&B,&E,&P,&n,&m);
	for(int  i=1; i<=m; i++) {
		scanf("%d%d",&x[i],&y[i]);
		z[i]=1;
	}
	for(int i=1; i<=3; i++) {
		memset(dp,63,sizeof(dp));
		for(int j=1; j<=m; j++) {
			tot(x[j],y[j],z[j]);
			tot(y[j],x[j],z[j]);
		}
		if(i==3) t=n;
		else t=i;
		spfa();
		memset(now,0,sizeof(now));//预处理
		for(int j=1; j<=n; j++)
			f[j][i]=flog[j];//保存最短路径
	}//做三次spfa
	for(int i=1; i<=n; i++) {
		int ans=f[i][1]*B+f[i][2]*E+f[i][3]*P;//算出以当前点为交汇点的权值
		if(ans<maxx)
			maxx=f[i][1]*B+f[i][2]*E+f[i][3]*P;//作比较
	}
	printf("%d",maxx);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值