poj 3013 Big Christmas Tree spfa

题目大意

  要建一棵圣诞树,使得总的花费最小。具体规则是:圣诞树是一颗无向树形图,其中,编号为1的节点为根节点,原始图中每条边具有边权,每个点也有一值权。圣诞树中,各条边的花费是该边权*该边的子树中所有点值,总的花费则是圣诞树中所有边的花费之和。

分析

  1.对点u,只有从点u到根结点之间的边会乘以点u的重量。

  2.所以,对于点u;最小的花费是要使点u到根结点的边权最小,即最短路。

  3.所以,圣诞树的最小总花费=每条边权*该边的子树中所有点值
                            =每个点值*该点到根结点的最短路

注意

  如果有的点无法到达,就要输出‘No Answer’

  如果输入的边数或点数为0,输出0(我wa了好多次)

  一定要注意范围,要用int64

代码

const
  maxe=100000;
  maxv=2000000;

type
  arr=record
    x,y,w,next:int64;
  end;

var
  n,m,s,q,nm:longint;
  ls:array[0..maxe] of longint;
  a:array[0..maxv] of arr;
  f:array[0..maxe] of int64;
  v:array[0..maxe] of int64;
  d,b:array[0..maxe] of int64;
  i,j,k,ll:longint;
  ans,max:int64;

procedure spfa;
var
  i,j,k:longint;
  head,tail:longint;
begin
  fillchar(f,sizeof(f),63);
  max:=f[1];
  head:=0;
  tail:=1;
  v[1]:=1;
  d[1]:=1;
  f[1]:=0;
  repeat
    head:=head+1;
    j:=ls[d[head]];
    while j<>0 do
      begin
        with a[j] do
          begin
            if f[x]+w<f[y]
              then
                begin
                  f[y]:=f[x]+w;
                  if v[y]=0
                    then
                      begin
                        tail:=tail+1;
                        d[tail]:=y;
                        v[y]:=1;
                      end;
                end;
            j:=next;
          end;
      end;
    v[d[head]]:=0;
  until head=tail;
end;

begin
  readln(nm);
  for ll:=1 to nm do
  begin
  fillchar(ls,sizeof(ls),0);
  fillchar(d,sizeof(d),0);
  fillchar(b,sizeof(b),0);
  fillchar(a,sizeof(a),0);
  fillchar(v,sizeof(v),0);
  readln(n,m);
  for i:=1 to n do
    read(b[i]);
  for i:=1 to m do
    begin
      with a[i*2-1] do
        begin
          readln(x,y,w);
          next:=ls[x];
          ls[x]:=i*2-1;
        end;
      a[i*2].x:=a[i*2-1].y;
      a[i*2].y:=a[i*2-1].x;
      a[i*2].w:=a[i*2-1].w;
      a[i*2].next:=ls[a[i*2].x];
      ls[a[i*2].x]:=i*2;
    end;
  m:=m*2;
  spfa;
  ans:=0;
  for i:=1 to n do
    if f[i]=max then break
                else ans:=f[i]*b[i]+ans;
  if (f[i]=max) then writeln('No Answer')
                else writeln(ans);
  end;
end.


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值