日常训练 20161102 隔离区

来源:互联网 发布:蒙文软件下载手机软件 编辑:程序博客网 时间:2024/06/06 18:08

题意简述:给出一个n个点的树(有边权),问删除其中一条边,剩下最长链的长度的期望。(乘n1输出)

题解:经典树形dp,用down1、down2、down3记录每个点向下的第一第二第三长链,up记录每个点向上最长链,son1、son2记录每个点有第一第二长链的两棵子树,dis记每个点到其父亲的边权,down_ans记录每个点向下的答案,lws是longest_without_subtree,是动态修改的,lws[x]记录对于枚举的当前x的一个儿子y,不包含y这棵子树的最长路。对于一个点,只要down_ans和lws取个max即可。

代码丑,不要看。。
type  edge=record         y,v,next:longint;       end;  rec=record        x:longint;        v:int64;      end;const  MAXN=500050;var  map:array[0..MAXN * 2] of edge;  down1,down2,down3,son1,son2:array[0..MAXN] of rec;  down_ans,up,lws:array[0..MAXN] of int64;  first,dis:array[0..MAXN] of longint;  s:longint;  ans:int64;function max(a,b:int64):int64;  begin if (a>b) then exit(a) else exit(b); end;procedure swap(var a,b:int64);  var t:int64;  begin t:=a;a:=b;b:=t; end;procedure ins(x,y,v:longint);  begin    inc(s);map[s].y:=y;map[s].v:=v;    map[s].next:=first[x];first[x]:=s;  end;procedure init;  var    n,i,x,y,v:longint;  begin    read(n);ans:=0;    for i:=1 to n-1 do      begin        read(x,y,v);        ins(x,y,v);        ins(y,x,v);      end;  end;procedure dfs1(x,f:longint);  var    t,y,v:longint;  begin    t:=first[x];    while (t>0) do      begin        y:=map[t].y;v:=map[t].v;        if (y<>f) then          begin            dfs1(y,x);dis[y]:=map[t].v;            if (down1[y].v+v>=down1[x].v)              then                begin                  down3[x]:=down2[x];                  down2[x]:=down1[x];                  down1[x].x:=y;                  down1[x].v:=down1[y].v+v;                end              else                if (down1[y].v+v>=down2[x].v)                  then                    begin                      down3[x]:=down2[x];                      down2[x].x:=y;                      down2[x].v:=down1[y].v+v;                    end                  else                    if (down1[y].v+v>down3[x].v) then                      begin                        down3[x].x:=y;                        down3[x].v:=down1[y].v+v;                      end;            if (down_ans[y]>=son1[x].v)              then                begin                  son2[x]:=son1[x];                  son1[x].x:=y;                  son1[x].v:=down_ans[y];                end              else                if (down_ans[y]>son2[x].v) then                  begin                    son2[x].x:=y;                    son2[x].v:=down_ans[y];                  end;            down_ans[x]:=max(down_ans[x],down_ans[y]);          end;        t:=map[t].next;      end;    down_ans[x]:=max(down_ans[x],down1[x].v+down2[x].v);  end;procedure dfs2(x,f:longint);  var    t:longint;  begin    t:=first[x];    if (x=1)      then up[x]:=0      else        begin          if (down1[f].x=x)            then up[x]:=down2[f].v            else up[x]:=down1[f].v;          up[x]:=max(up[x],up[f]);          inc(up[x],dis[x]);        end;    while (t>0) do      begin        if (map[t].y<>f)          then dfs2(map[t].y,x);        t:=map[t].next;      end;  end;procedure dfs3(x,f:longint);  var    t,y:longint;    t1,t2,t3:int64;  begin    t:=first[x];    if (x<>1) then ans:=ans+max(down_ans[x],lws[f]);    while (t>0) do      begin        y:=map[t].y;        if (y<>f) then          begin            if (down1[x].x=y)              then begin t1:=down2[x].v;t2:=down3[x].v;end              else if (down2[x].x=y)                     then begin t1:=down1[x].v;t2:=down3[x].v;end                     else begin t1:=down1[x].v;t2:=down2[x].v;end;            t3:=up[x];            if (t1<t3) then swap(t1,t3);            if (t2<t3) then swap(t2,t3);            if (son1[x].x=y)              then lws[x]:=max(son2[x].v,lws[f])              else lws[x]:=max(son1[x].v,lws[f]);            lws[x]:=max(lws[x],t1+t2);            dfs3(y,x);          end;        t:=map[t].next;      end;  end;begin  assign(input,'split.in');reset(input);  assign(output,'split.out');rewrite(output);  init;  dfs1(1,0);  dfs2(1,0);  dfs3(1,0);  writeln(ans);  close(input);close(output);end.
0 0
原创粉丝点击