[最短路] 3.2.6 Sweet Butter

Sweet Butter
香甜的黄油

Greg Galperin -- 2001

by kd

    农夫John发现做出全威斯康辛州最甜的黄油的方法: 糖。把糖放在一片牧场上,他知道N(1<=N<=500)只奶牛会过来舔它,这样就能做出能卖好价钱的超甜黄油。当然,他将付出额外的费用在 奶牛上。

  农夫John很狡猾。像以前的Pavlov,他知道他可以训练这些奶牛,让它们在听到铃声时去一个特定的牧场。他打算将糖放在那里然后下午发出铃声,以至他可以在晚上挤奶。

  农夫John知道每只奶牛都在各自喜欢的牧场(一个牧场不一定只有一头牛)。给出各头牛在的牧场和牧场间的路线,找出使所有牛到达的路程和最短的牧场(他 将把糖放在那)

PROGRAM NAME: butter

INPUT FORMAT

第一行: 三个数:奶牛数N,牧场数(2<=P<=800),牧场间道路数C(1<=C<=1450)

第二行到第N+1行: 1到N头奶牛所在的牧场号

第N+2行到第N+C+1行: 每行有三个数:相连的牧场A、B,两牧场间距离D(1<=D<=255),当然,连接是双向的

SAMPLE INPUT (file butter.in)

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
}

OUTPUT FORMAT

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

SAMPLE OUTPUT (file butter.out)

 8
{说明:
 放在4号牧场最优
}
 
 
 
 
枚举每个牧场k,求出其余所有牧场到此牧场的最短路径。
每次可以得到一个值tot,为各个牧场的奶牛数*该牧场到s最短路径。
取所有tot 最小的即可。
 
求最短路径用spfa+链式前向星  
 
 
var i,n,p,c,dd,d1,d2,d3,ans:longint;
    num,d:array[1..800]of longint;
    h:array[1..20000]of longint;
    v:array[1..800]of boolean;
    w,next,e,head:array[1..3000]of longint;

procedure insert(a,b,s,i:longint);
begin
    next[i]:=head[a];
    e[i]:=b;
    w[i]:=s;
    head[a]:=i;
end;

procedure spfa(k:longint);
var i,hea,tail,s,tot,kk:longint;
begin
    fillchar(h,sizeof(h),0);
    fillchar(v,sizeof(v),false);
    for i:=1 to p do d[i]:=maxlongint;
    d[k]:=0;hea:=1;tail:=1;h[1]:=k;v[k]:=true;
    while hea<=tail do
    begin
         s:=h[hea];
         kk:=head[s];
         while kk<>0 do
         begin
            if (w[kk]+d[s]<d[e[kk]]) then
            begin
                 d[e[kk]]:=w[kk]+d[s];
                 if (v[e[kk]]<>true) then
                     begin
                         inc(tail);
                         h[tail]:=e[kk];
                         v[e[kk]]:=true;
                     end;
             end;
             kk:=next[kk];
         end;
         v[s]:=false;
         inc(hea);
    end;
    tot:=0;
    for i:=1 to p do if num[i]<>0 then tot:=tot+num[i]*d[i];
    if ans>tot then ans:=tot;
end;

begin
    fillchar(head,sizeof(head),0);
    fillchar(next,sizeof(next),0);
    readln(n,p,c);ans:=maxlongint;
    for i:=1 to n do begin read(dd); inc(num[dd]); end;
    for i:=1 to c do
    begin
        readln(d1,d2,d3);
        insert(d1,d2,d3,i*2);
        insert(d2,d1,d3,i*2+1);
    end;
    for i:=1 to p do
    spfa(i);
    writeln(ans);
end.




 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值