USACO 3.2 Sweet Butter 香甜的黄油 (Bellman DIJ SPFA)

Description

  农夫John发现做出全威斯康辛州最甜的黄油的方法:糖。把糖放在一片牧场上,他知道N(1<=N<=500)只奶牛会过来舔它,这样就能做出能卖好价钱的超甜黄油。当然,他将付出额外的费用在奶牛上。
  农夫John很狡猾。像以前的Pavlov,他知道他可以训练这些奶牛,让它们在听到铃声时去一个特定的牧场。他打算将糖放在那里然后下午发出铃声,以至他可以在晚上挤奶。
  农夫John知道每只奶牛都在各自喜欢的牧场(一个牧场不一定只有一头牛)。给出各头牛在的牧场和牧场间的路线,找出使所有牛到达的路程和最短的牧场(他将把糖放在那)

Input

第一行: 三个数:奶牛数N,牧场数(2<=P<=800),牧场间道路数C(1<=C<=1450)
第二行到第N+1行: 1到N头奶牛所在的牧场号
第N+2行到第N+C+1行: 每行有三个数:相连的牧场A、B,两牧场间距离D(1<=D<=255),当然,连接是双向的

Output

一行 输出奶牛必须行走的最小的距离和

Sample Input

3 4 5
2
3
4
1 2 1
1 3 5
2 3 7
2 4 3
3 4 5
样例图形
P2
P1 @–1–@ C1
\ |\
\ | \
5 7 3
\ | \
| \ C3
C2 @–5–@
P3 P4
Sample Output

8
{说明:放在4号牧场最优 }
Source

FZY-FHN

题解:

因为是无向图,所以枚举放的点作为起点SPFA算出分别到达其他点的距离即可

代码:

var
  l,n,m,h,t,ans:longint;
  num,dist:array [0..801] of longint;
  a,b:array [0..801,0..801] of longint;
  d:array [0..20001] of integer;
  v:array [0..801] of boolean;
procedure init;
var
  i,j,x,y,z:longint;
begin
  fillchar(num,sizeof(num),0);
  fillchar(a,sizeof(a),$7f div 2);
  read(l,n,m);
  for i:=1 to l do
    begin
      read(x);
      inc(num[x]);
    end;
  for i:=1 to m do
    begin
      read(x,y,z);
      inc(b[x,0]); b[x,b[x,0]]:=y; a[x,y]:=z;
      inc(b[y,0]); b[y,b[y,0]]:=x; a[y,x]:=z;
    end;
end;

procedure spfa(s:longint);
var
  i,tk,sum:longint;
begin
  fillchar(d,sizeof(d),0);
  fillchar(v,sizeof(v),false);
  fillchar(dist,sizeof(dist),$7f div 2);
  dist[s]:=0; v[s]:=true; d[1]:=s; h:=0; t:=1;
  repeat
    tk:=d[h];
    for i:=1 to b[tk,0] do
      if dist[b[tk,i]]>dist[tk]+a[tk,b[tk,i]] then
        begin
          dist[b[tk,i]]:=dist[tk]+a[tk,b[tk,i]];
          if not v[b[tk,i]] then
            begin
              inc(t);
              d[t]:=b[tk,i];
              v[b[tk,i]]:=true;
            end;
        end;
    v[tk]:=false;
    inc(h);
  until h>t;
  sum:=0;
  for i:=1 to n do
    inc(sum,dist[i]*num[i]);
  if ans>sum then ans:=sum;
end;

procedure main;
var
  i:longint;
begin
  ans:=maxlongint;
  for i:=1 to n do
    spfa(i);
  write(ans);
end;

begin
  init;
  main;
end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值