jzoj4311 统一天下

Description

这里写图片描述

Input

这里写图片描述

Output

这里写图片描述

Sample Input

4 4
1 3
2 1
4 3
4 3
4 1
1 2

Sample Output

68

Data Constraint

这里写图片描述

算法讨论

问题的关键是如何求出两棵树的重心,那就是f[i],即所有点到点i的距离,首先dfs一次求出f[1]和z[i](i的子树的大小),那么就可以进行树形dp,父亲节点为i,儿子节点为j,f[j]:=f[i]+n-2*f[j],找出左右两棵树最小的f[i],相连即可。
type node=^link;
link=record
     g:longint;
     next:node;
end;
var
  nd:array[1..2,1..300000]of node;
  n,m,l:longint;
  f,z:array[1..2,0..300000] of int64;
  t:array[0..300000] of boolean;
procedure dfs(wei,e:longint);
var
  p:node;
begin
  f[l,1]:=f[l,1]+e;
  t[wei]:=false;
  p:=nd[l,wei];
  while p<>nil do
    begin
      if t[p^.g] then
        begin
          dfs(p^.g,e+1);
          z[l,wei]:=z[l,wei]+z[l,p^.g]+1;
        end;
      p:=p^.next;
    end;
end;
procedure df(wei:longint);
var
  p:node;
begin
  t[wei]:=false;
  p:=nd[l,wei];
  while p<>nil do
    begin
      if t[p^.g] then
        begin
          f[l,p^.g]:=f[l,wei]-2*(z[l,p^.g]+1);
          if l=1 then inc(f[l,p^.g],n)
          else inc(f[l,p^.g],m);
          df(p^.g);
        end;
      p:=p^.next;
    end;
end;
procedure ad(u,v,w:longint);
var
  p:node;
begin
  new(p);
  p^.g:=v;
  p^.next:=nd[w,u];
  nd[w,u]:=p;
end;
var
  u,v,i:longint;
  sum,xx,yy:int64;
begin
  assign(input,'a.in');reset(input);
  readln(n,m);
  for i:=1 to n-1 do
    begin
      readln(u,v);
      ad(u,v,1);
      ad(v,u,1);
    end;
  for i:=1 to m-1 do
    begin
      readln(u,v);
      ad(u,v,2);
      ad(v,u,2);
    end;
  fillchar(t,sizeof(t),true);
  l:=1;
  dfs(1,0);
  fillchar(t,sizeof(t),true);
  df(1);
  fillchar(t,sizeof(t),true);
  l:=2;
  dfs(1,0);
  fillchar(t,sizeof(t),true);
  df(1);
  xx:=9223372036854775807;
  yy:=xx;
  for i:=1 to n do
    begin
      if f[1,i]<xx then xx:=f[1,i];
      sum:=sum+f[1,i];
    end;
  for i:=1 to m do
    begin
      if f[2,i]<yy then yy:=f[2,i];
      sum:=sum+f[2,i];
    end;
  writeln(sum div 2+xx*m+yy*n+n*m);
end.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值