poj 3013 Big Christmas Tree spfa

来源:互联网 发布:fedora yum 源 编辑:程序博客网 时间:2024/05/20 04:31

题目大意

  要建一棵圣诞树,使得总的花费最小。具体规则是:圣诞树是一颗无向树形图,其中,编号为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