P2939 [USACO09FEB]改造路Revamping Trails(迪杰斯特拉+堆优化)

约翰一共有N)个牧场.由M条布满尘埃的小径连接.小径可 以双向通行.每天早上约翰从牧场1出发到牧场N去给奶牛检查身体.

通过每条小径都需要消耗一定的时间.约翰打算升级其中K条小径,使之成为高 速公路.在高速公路上的通行几乎是瞬间完成的,所以高速公路的通行时间为0.

请帮助约翰决定对哪些小径进行升级,使他每天早上到牧场W花的时间最少.输出这个最少 的时间.

输入输出格式

输入格式:
Line 1: Three space-separated integers: N, M, and K

Lines 2..M+1: Line i+1 describes trail i with three space-separated integers: P1_i, P2_i, and T_i
输出格式:
Line 1: The length of the shortest path after revamping no more than K edges
输入输出样例

输入样例#1: 复制
4 4 1
1 2 10
2 4 10
1 3 1
3 4 100
输出样例#1: 复制
1
说明

K is 1; revamp trail 3->4 to take time 0 instead of 100. The new shortest path is 1->3->4, total traversal time now 1.

又是一道卡spfa的裸题



program df;
type point=^node;
node=record
date:int64;
ends:longint;
next:point;
end;
type ccdd=record
x,y:longint;
end;
var i,j,n,m,x,y,z,k,t,len:longint;
ans:int64;
path:array[0..100000] of point;
a:array[0..2000000] of int64;
dis:array[0..100000,0..20] of int64;
c:array[0..100000,0..20] of boolean;
b:array[0..2000000] of ccdd;
procedure add(xx:int64;y,z:longint);
var i,dd:int64;
d2:ccdd;
begin
inc(len);
a[len]:=xx;
b[len].x:=y;
b[len].y:=z;
//writeln('min ',len,' ',a[len]);
i:=len;
while (i>1) and (a[i div 2]>a[i]) do
begin
dd:=a[i div 2]; a[i div 2]:=a[i]; a[i]:=dd;
d2:=b[i div 2]; b[i div 2]:=b[i]; b[i]:=d2;
i:=i div 2;
end;
end;


function get:ccdd;
var i,j,dd:int64;
d2:ccdd;
begin
get:=b[1];
a[1]:=a[len];
b[1]:=b[len];
dec(len);
i:=1;
while i*2<=len do
begin
if (i*2+1>len) or (a[i*2]<a[i*2+1]) then j:=i*2
else j:=i*2+1;
if a[i]>a[j] then
begin
dd:=a[i]; a[i]:=a[j]; a[j]:=dd;
d2:=b[i]; b[i]:=b[j]; b[j]:=d2;
i:=j;
end else break;
end;
end;

procedure com(x,y,z:longint);
var i:point;
begin
i:=path[x];
new(path[x]);
path[x]^.ends:=y;
path[x]^.date:=z;
path[x]^.next:=i;
end;

procedure djs(x:longint);
var i:point;
y,u,ans:longint;
a,b:ccdd;
begin
i:=path[x];
len:=0;
dis[x,0]:=0;
add(0,x,0);

while len>0 do
begin

a:=get;
while (c[a.x,a.y]=true) and (len>0) do a:=get;
if (c[a.x,a.y]=true) and (len=0) then exit;

i:=path[a.x];
c[a.x,a.y]:=true;
while i<>nil do
begin
y:=i^.ends;


if a.y+1<=k then 
if dis[y,a.y+1]>dis[a.x,a.y] then
begin
dis[y,a.y+1]:=dis[a.x,a.y];
if not c[y,a.y+1] then add(dis[y,a.y+1],y,a.y+1);
end;


if dis[y,a.y]>dis[a.x,a.y]+i^.date then
begin
dis[y,a.y]:=dis[a.x,a.y]+i^.date;
if (not c[y,a.y]) then add(dis[y,a.y],y,a.y);
end;


i:=i^.next;
end;

end;

end;





begin
readln(n,m,k);
for i:=0 to n do
for j:=0 to k do
dis[i,j]:=9999999999999;
for i:=1 to m do
begin
readln(x,y,z);
com(x,y,z);
com(y,x,z);
end;
djs(1);

ans:=dis[0,0];
for j:=0 to k do
if dis[n,j]<ans then ans:=dis[n,j];
writeln(ans);
end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是P4087 [USACO17DEC]Milk Measurement的c++代码: ```c++ #include<bits/stdc++.h> using namespace std; int n,d,i,x,minn=1e9,maxn=-1e9,sum=7;//注意sum要初始化为7,因为一开始有三个人挤奶! map<int,int> mp; struct node{ int day,milk,id;//day表示某一天,milk表示这一天的产奶量,id表示这头牛的编号 }a[100010]; bool cmp(node x,node y){ return x.day<y.day; } int main(){ scanf("%d%d",&n,&d); for(i=1;i<=n;i++){ scanf("%d%d%d",&a[i].day,&a[i].id,&a[i].milk); minn=min(minn,a[i].id);//记录最小的牛的编号 maxn=max(maxn,a[i].id);//记录最大的牛的编号 } sort(a+1,a+n+1,cmp);//排序 for(i=1;i<=n;i++){ int p=a[i].id; mp[p]+=a[i].milk;//记录每头牛产奶总量 if(mp[p]-a[i].milk>=mp[minn]&&mp[p]>=mp[minn]){//如果这头牛的产奶总量减去这一天的产奶量后等于最小产奶量且这头牛的产奶总量大于等于最小产奶量 sum--; } if(mp[p]>=mp[maxn]&&mp[p]-a[i].milk<mp[maxn]){//如果这头牛的产奶总量大于等于最大产奶量且这头牛的产奶总量减去这一天的产奶量小于最大产奶量 sum++; } if(mp[p]-a[i].milk<mp[maxn]&&mp[p]>=mp[maxn]){//如果这头牛的产奶总量减去这一天的产奶量小于最大产奶量且这头牛的产奶总量大于等于最大产奶量 if(mp[maxn]-mp[p]+a[i].milk>0)sum++; } mp[p]-=a[i].milk;//减去这一天的产奶量 if(i==n||a[i].day!=a[i+1].day){//如果到了新的一天或者到了最后一天 if(mp[maxn]!=mp[a[i].id]&&mp[a[i].id]>=mp[maxn])sum++;//如果这头牛的产奶总量不等于最大产奶量且这头牛的产奶总量大于等于最大产奶量 if(mp[maxn]==mp[a[i].id]){//如果这头牛的产奶总量等于最大产奶量 if(a[i].id==maxn)sum+=0;//如果这头牛就是最大产奶量的牛,那么不需要增加计数器 else sum++;//否则需要增加计数器 } if(mp[minn]!=mp[a[i].id]&&mp[a[i].id]>=mp[minn])sum++;//如果这头牛的产奶总量不等于最小产奶量且这头牛的产奶总量大于等于最小产奶量 if(mp[minn]==mp[a[i].id]){ if(a[i].id==minn)sum+=0;//如果这头牛就是最小产奶量的牛,那么不需要增加计数器 else sum++;//否则需要增加计数器 } } } printf("%d\n",sum); return 0; } ``` 该题的解题思是模拟,需要注意细节问题。我们可以首先将输入的数据按天数排序,然后模拟每一天挤奶的情况,并根据题目要求进行计数即可。具体细节请见代码注释。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值