[BZOJ3611] [Heoi2014]大工程
2016-03-04 18:47
399 查看
传送门
http://www.lydsy.com/JudgeOnline/problem.php?id=3611题目大意
给定一些树上的关键点询问1.两两之间的路径和
2.两两之间的最长路径
3.两两之间的最短路径
题解
虚树+树形DP第一个问题
f[i]+=f[son[i]]+size[son[i]]∗(cnt−size[son[i]])∗dis(i,son[i])f[i]+=f[son[i]]+size[son[i]]*(cnt-size[son[i]])*dis(i,son[i])
cntcnt为关键点总数,size[i]size[i]为以ii为根的子树内关键点个数
第二,三个问题
minans=min(minans,g[i]+g[son[i]]+dis(i,son[i]))minans=min(minans,g[i]+g[son[i]]+dis(i,son[i]))
g[i]g[i]为以ii为根的子树中到ii的最小长度
maxmax同理
注意初值
const maxn=1000050; maxint=1000000000; var w:array[0..3*maxn,1..2]of longint; t,x,dep,pos,g,h,cle:array[0..maxn]of longint; {g-->min;h-->max} size,f:array[0..maxn]of int64; st:array[0..maxn,0..20]of longint; i,j,k:longint; n,m,len,a,b,top,cnt,ans1,ans2,tt:Longint; {ans1-->min;ans2-->max} function min(a,b:longint):longint; begin if a>b then exit(b) else exit(a); end; function max(a,b:longint):longint; begin if a<b then exit(b) else exit(a); end; procedure init(a,b:longint); begin w[len,1]:=b; if w[a,2]=0 then w[a,2]:=len else w[w[a,1],2]:=len; w[a,1]:=len; inc(len); end; procedure sort(l,r:longint); var i,j,a,b:longint; begin i:=l; j:=r; a:=pos[x[(l+r)div 2]]; repeat while (pos[x[i]]<a) do inc(i); while (a<pos[x[j]]) do dec(j); if not (i>j) then begin b:=x[i]; x[i]:=x[j]; x[j]:=b; inc(i); dec(j); end; until i>j; if l<j then sort(l,j); if i<r then sort(i,r); end; procedure dfs(a,fa:longint); var tt:longint; begin tt:=w[a,2]; inc(len); pos[a]:=len; st[a,0]:=fa; while tt<>0 do begin if (w[tt,1]<>fa) then begin dep[w[tt,1]]:=dep[a]+1; dfs(w[tt,1],a); end; tt:=w[tt,2]; end; end; function lca(a,b:longint):longint; var i:longint; begin if dep[a]<dep[b] then begin i:=a; a:=b; b:=i; end; for i:=20 downto 0 do if dep[st[a,i]]>=dep[b] then a:=st[a,i]; if a=b then exit(a); for i:=20 downto 0 do if st[a,i]<>st[b,i] then begin a:=st[a,i]; b:=st[b,i]; end; exit(st[a,0]); end; procedure dp(a,fa:longint); {g-->min;h-->max} {ans1-->min;ans2-->max} begin f[fa]:=f[fa]+f[a]+size[a]*(cnt-size[a])*(dep[a]-dep[fa]); size[fa]:=size[fa]+size[a]; ans1:=min(ans1,g[fa]+g[a]+dep[a]-dep[fa]); ans2:=max(ans2,h[fa]+h[a]+dep[a]-dep[fa]); g[fa]:=min(g[fa],g[a]+dep[a]-dep[fa]); h[fa]:=max(h[fa],h[a]+dep[a]-dep[fa]); end; begin readln(n); len:=n+1; for i:=1 to n-1 do begin readln(a,b); init(a,b); init(b,a); end; init(0,1); init(1,0); len:=0; dep[0]:=1; st[0,0]:=0; dfs(0,0); for j:=1 to 20 do for i:=1 to n do st[i,j]:=st[st[i,j-1],j-1]; for i:=0 to n do begin g[i]:=maxint; h[i]:=-maxint; end; readln(m); for i:=1 to m do begin readln(cnt); for j:=1 to cnt do begin read(x[j]); size[x[j]]:=1; cle[j]:=x[j]; g[x[j]]:=0; h[x[j]]:=0; end; sort(1,cnt); top:=1; t[1]:=0; cle[0]:=cnt+1; cle[cnt+1]:=0; ans1:=maxint; ans2:=-maxint; for j:=1 to cnt do begin tt:=lca(t[top],x[j]); while (dep[tt]<dep[t[top]]) do begin if (dep[t[top-1]]<=dep[tt]) then begin dp(t[top],tt); {dp(t[top]-->tt)} dec(top); if (t[top]<>tt) then begin inc(top); t[top]:=tt; inc(cle[0]); cle[cle[0]]:=tt; end; break; end; dp(t[top],t[top-1]); {dp(t[top]-->t[top-1])} dec(top); end; inc(top); t[top]:=x[j]; end; while (top>1) do begin dp(t[top],t[top-1]); {dp(t[top]-->t[top-1])} dec(top); end; writeln(f[0],' ',ans1,' ',ans2); for j:=1 to cle[0] do begin size[cle[j]]:=0; f[cle[j]]:=0; g[cle[j]]:=maxint; h[cle[j]]:=-maxint; end; end; end.
相关文章推荐
- bzoj2143 飞飞侠 最短路
- poj 3723 Conscription(最大生成树)
- 字符串常量举例
- 优雅的实现图片翻转(js实现)
- 学习python入门(一)
- HDU 1856 More is better
- jQuery 实现页面关键字查询
- Java面试题多思路解析--有一个已经排好序的数组。现输入一个数,要求按原来的规律将它插入数组中
- verilog的小数问题
- 10、Cocos2dx 3.0游戏开发找小三之容器篇:Vector、Map、Value
- ASP.NET导入导出
- 6-11-N皇后问题-树和二叉树-第6章-《数据结构》课本源码-严蔚敏吴伟民版
- POJ1523--SPF--tarjan--割点--分块
- NTV Media Server G3流媒体服务器搭建经验
- bzoj2118 墨墨的等式 最短路
- 【Xamarin挖墙脚系列:Xamarin 上台讲述PPT呵呵呵】
- ios tableView reload不是异步
- Android控件ListView
- 7.6实战练习
- 数据结构与算法笔记 —— 绪论