Problem : [Usaco2014 Dec]Piggy Back
Time Limit: 1 Sec Memory Limit: 128 MB
Description
Bessie and her sister Elsie graze in different fields during the day,and in the evening they both want to walk back to the barn to rest.Being clever bovines, they come up with a plan to minimize the total amount of energy they both spend while walking.
Bessie spends B units of energy when walking from a field to an adjacent field, and Elsie spends E units of energy when she walks to an adjacent field. However, if Bessie and Elsie are together in the same field, Bessie can carry Elsie on her shoulders and both can move to an adjacent field while spending only P units of energy (where P might be considerably less than B+E, the amount Bessie and Elsie would have spent individually walking to the adjacent field). If P is very small, the most energy-efficient solution may involve Bessie and Elsie traveling to a common meeting field, then traveling together piggyback for the rest of the journey to the barn. Of course, if P is large, it may still make the most sense for Bessie and Elsie to travel separately. On a side note, Bessie and Elsie are both unhappy with the term “piggyback”, as they don’t see why the pigs on the farm should deserve all the credit for this remarkable form of transportation.
Given B, E, and P, as well as the layout of the farm, please compute the minimum amount of energy required for Bessie and Elsie to reach the barn.
贝茜和妹妹埃尔茜白天在不同的田里吃草,
到了晚上,他们都想步行回谷仓休息。
他们是聪明的牛,他们想出了一个计划,把总数降到最低。
他们走路时消耗的能量。
贝茜从一块地走到另一块地时,花费了B单位的能量。
当埃尔茜走到附近的区域时,她会消耗E单位的能量。
相邻字段。但是,如果贝茜和埃尔茜在一起同一块地,贝茜可以把埃尔茜扛在肩上,两人都可以移动。在只消耗p单位能量的情况下(其中p可能比B+E少得多,贝茜和埃尔茜的数量单独步行到邻近的田地)。如果p非常小,最节能的解决方案可能涉及贝茜和埃尔茜到一个共同的会议场地旅行,然后一起背着旅行在去谷仓的剩余旅程中。当然,如果p很大可能对贝茜和埃尔茜来说最有意义的旅行分开。旁注,贝茜和埃尔茜都不满意俚语“骑小猪”,因为他们不明白为什么农场上的猪应该为这种非凡的荣誉。
给定B、E和P,以及农场的布局,请计算贝西和埃尔西达到所需的最小能量谷仓。
HINT
给定一个N个点M条边的无向图,其中贝茜在1号点,埃尔茜在2号点,它们的目的地为N号点。贝茜每经过一条边需要消耗B点能量,埃尔茜每经过一条边需要消耗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.
输入的第一行包含正整数b、e、p、n和M.
所有这些都不超过40000。B、E和P如上所述。
n是农场中的田地数(编号1…n,其中n大于等于3),m是字段之间的连接数。
贝茜和埃尔茜分别从字段1和2开始。
谷仓位于北郊。
输入中接下来的m行分别描述了一对不同的字段,由两个字段的整数索引指定领域。
连接是双向的。
总是有可能沿序列从字段1到字段N,从字段2到字段N这种联系。
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.
指定最小能量的单个整数,贝茜和埃尔茜总得花点力气才能到达谷仓。
在这个例子中如图所示,贝茜从1到4,Elsie从2到3到4。
然后,他们一起从4点到7点到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
HINT
第一步是看我们能把贝西和埃尔西的旅行分成两部分:开始直到他们相遇和背在一起,然后背在一起直到结束(如果他们从来没有背在一起,那和在结束时相遇一样,然后背在一起0距离)。
如果我们知道他们在哪里相遇,问题就容易了。假设他们在第二十场见面。然后从xx开始,我们可以使用bfs计算到所有其他字段的最快路径。然后,如果Didi边缘从字段xx移动到字段ii,则答案是b d1+e d2+p dn b d1+e d2+p dn。
这已经为我们提供了一个O(n2)O(n2)解决方案;只需尝试每个xx。要将其加速到o(n)o(n),请注意,我们总是希望字段11、22和n n之间的距离。因此,如果我们预先计算这些距离,就需要O(1)O(1)时间来尝试每个XX。
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define up(i,j,k) for(int i=j;i<=k;i++)
#define maxn 40010
using namespace std;
inline int read() {
char ch=getchar();
int f=1,x=0;
while(ch<'0'||ch>'9') {
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return f*x;
}
struct e {
int t,n;
} es[maxn*2];
int ess,g[maxn];
void pe(int f,int t) {
es[++ess]=(e) {
t,g[f]
};
g[f]=ess;
es[++ess]=(e) {
f,g[t]
};
g[t]=ess;
}
int n,m,b,e,p,d[3][maxn];
long long ans;
queue<int>q;
bool vis[maxn];
void bfs(int s,int o) {
while(!q.empty())q.pop();
memset(vis,0,sizeof(vis));
q.push(s);
vis[s]=1;
d[o][s]=0;
while(!q.empty()) {
int x=q.front();
q.pop();
for(int i=g[x]; i; i=es[i].n)if(!vis[es[i].t]) {
d[o][es[i].t]=d[o][x]+1;
q.push(es[i].t);
vis[es[i].t]=1;
}
}
}
int main() {
scanf("%d %d %d %d %d",&b,&e,&p,&n,&m);
up(i,1,m) {
int x=read(),y=read();
pe(x,y);
}
bfs(1,0);
bfs(2,1);
bfs(n,2);
ans=1LL*d[0][n]*b+1LL*d[1][n]*e;
up(i,1,n)if(1LL*d[0][i]*b+1LL*d[1][i]*e+1LL*d[2][i]*p<ans)ans=1LL*d[0][i]*b+1LL*d[1][i]*e+1LL*d[2][i]*p;
printf("%lld",ans);
return 0;
}