[HEOI2014]大工程
题目描述
国家有一个大工程,要给一个非常大的交通网络里建一些新的通道。
我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上。
在 2 个国家 a,b 之间建一条新通道需要的代价为树上 a,b 的最短路径。
现在国家有很多个计划,每个计划都是这样,我们选中了 k 个点,然后在它们两两之间 新建 C(k,2)条 新通道。现在对于每个计划,我们想知道: 1.这些新通道的代价和 2.这些新通道中代价最小的是多少 3.这些新通道中代价最大的是多少
输入输出格式
输入格式:
第一行 n 表示点数。
接下来 n-1 行,每行两个数 a,b 表示 a 和 b 之间有一条边。点从 1 开始标号。
接下来一行 q 表示计划数。对每个计划有 2 行,第一行 k 表示这个计划选中了几个点。
第二行用空格隔开的 k 个互不相同的数表示选了哪 k 个点。
输出格式:
输出 q 行,每行三个数分别表示代价和,最小代价,最大代价。
输入输出样例
10 2 1 3 2 4 1 5 2 6 4 7 5 8 6 9 7 10 9 5 2 5 4 2 10 4 2 5 2 2 6 1 2 6 1
3 3 3 6 6 6 1 1 1 2 2 2 2 2 2
说明
对于第 1,2 个点: n<=10000
对于第 3,4,5 个点: n<=100000,交通网络构成一条链
对于第 6,7 个点: n<=100000
对于第 8,9,10 个点: n<=1000000
对于所有数据, q<=50000并且保证所有k之和<=2*n
看到k的和小于2*n,于是立刻想到建虚树
建出虚树后就dp
size[x]表示x的子树中关键点数
f[x]表示x子树中路径的贡献和
Min[x]表示x子树中离x距离最小的关键点的距离
Max[x]表示最大的距离
最大值和求和很简单
最大值总是要取到叶子节点,虚树中叶子节点总是关键点
答案取当前Max[x]+Max[v]+边权w,然后Max[x]=max(Max[x],Max[v]+d)
求和就考虑一条边的贡献
一条边的贡献次数显然是size[v]*(k-size[v])
所以f[x]+=f[v]+size[v]*(k-size[v])*w
求最小值的话,Min[x]初值正无穷
如果是关键点就直接取它的子树路径最小值,否则就是它的两个儿子的子树路径最小值相加
如果是关键点,更新答案后Min[x]要清0,作为接下来的端点
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 typedef long long lol; 8 const int N=2000005; 9 struct Node 10 { 11 int next,to; 12 }edge[N],edge2[N]; 13 int inf=1e9; 14 int dep[N],fa[N][21],dfn[N],cnt,bin[25],head[N],head2[N],num,ed[N]; 15 int size[N],vis[N],Max[N],Min[N],k,M,ans1,ans2,n,Lca,a[N],s[N],top; 16 lol f[N]; 17 int gi() 18 { 19 char ch=getchar(); 20 int x=0; 21 while (ch<'0'||ch>'9') ch=getchar(); 22 while (ch>='0'&&ch<='9') 23 { 24 x=x*10+ch-'0'; 25 ch=getchar(); 26 } 27 return x; 28 } 29 bool cmp(int a,int b) 30 { 31 return dfn[a]<dfn[b]; 32 } 33 void add(int u,int v) 34 { 35 num++; 36 edge[num].next=head[u]; 37 head[u]=num; 38 edge[num].to=v; 39 } 40 void add2(int u,int v) 41 { 42 if (u==v) return; 43 num++; 44 edge2[num].next=head2[u]; 45 head2[u]=num; 46 edge2[num].to=v; 47 } 48 void dfs(int x,int pa) 49 {int i; 50 dep[x]=dep[pa]+1; 51 dfn[x]=++cnt; 52 for (i=1;bin[i]<=dep[x];i++) 53 fa[x][i]=fa[fa[x][i-1]][i-1]; 54 for (i=head[x];i;i=edge[i].next) 55 { 56 int v=edge[i].to; 57 if (v==pa) continue; 58 fa[v][0]=x; 59 dfs(v,x); 60 } 61 ed[x]=cnt; 62 } 63 int lca(int x,int y) 64 {int as,i; 65 if (dep[x]<dep[y]) swap(x,y); 66 for (i=20;i>=0;i--) 67 if (bin[i]<=dep[x]-dep[y]) 68 x=fa[x][i]; 69 if (x==y) return x; 70 for (i=20;i>=0;i--) 71 { 72 if (fa[x][i]!=fa[y][i]) 73 { 74 x=fa[x][i];y=fa[y][i]; 75 } 76 } 77 return fa[x][0]; 78 } 79 80 void dp(int x) 81 {int i; 82 size[x]=vis[x]; 83 Max[x]=0;Min[x]=inf;f[x]=0; 84 for (i=head2[x];i;i=edge2[i].next) 85 { 86 int v=edge2[i].to,d=dep[v]-dep[x]; 87 dp(v); 88 size[x]+=size[v]; 89 f[x]+=f[v]+1ll*size[v]*(k-size[v])*d; 90 ans1=min(ans1,Min[x]+Min[v]+d);Min[x]=min(Min[x],Min[v]+d); 91 ans2=max(ans2,Max[x]+Max[v]+d);Max[x]=max(Max[x],Max[v]+d); 92 } 93 if (vis[x]) ans1=min(ans1,Min[x]),ans2=max(ans2,Max[x]),Min[x]=0; 94 } 95 int main() 96 {int i,u,v,j,q; 97 cin>>n; 98 bin[0]=1; 99 for (i=1;i<=20;i++) 100 bin[i]=bin[i-1]*2; 101 for (i=1;i<=n-1;i++) 102 { 103 scanf("%d%d",&u,&v); 104 add(u,v);add(v,u); 105 } 106 dfs(1,0); 107 cin>>q; 108 while (q--) 109 { 110 k=gi(); 111 M=k; 112 num=0;ans1=inf;ans2=0; 113 for (i=1;i<=k;i++) 114 a[i]=gi(),vis[a[i]]=1; 115 sort(a+1,a+k+1,cmp); 116 Lca=a[1]; 117 for (i=2;i<=k;i++) 118 if (ed[a[i-1]]<dfn[a[i]]) 119 a[++M]=lca(a[i-1],a[i]),Lca=lca(Lca,a[i]); 120 a[++M]=Lca; 121 sort(a+1,a+M+1,cmp); 122 M=unique(a+1,a+M+1)-a-1; 123 s[++top]=a[1]; 124 for (i=2;i<=M;i++) 125 { 126 while (top&&ed[s[top]]<dfn[a[i]]) top--; 127 add2(s[top],a[i]); 128 s[++top]=a[i]; 129 } 130 dp(Lca); 131 printf("%lld %d %d\n",f[Lca],ans1,ans2); 132 for (i=1;i<=M;i++) 133 vis[a[i]]=head2[a[i]]=0; 134 } 135 }
转载于:https://www.cnblogs.com/Y-E-T-I/p/8454972.html
[HEOI2014]大工程相关推荐
- BZOJ3611: [Heoi2014]大工程
题解:虚树模板题 维护虚树 跑树dp即可 /**************************************************************Problem: 3611Use ...
- P4103 [HEOI2014]大工程
P4103 [HEOI2014]大工程 题目描述 详见:P4103 [HEOI2014]大工程 Solution 显然是虚树的板子题啊(我也不造我为啥调了1h) 直接建虚树,DP. 两两路径和很好求, ...
- bzoj 3611: [Heoi2014]大工程(虚树+树形DP)
3611: [Heoi2014]大工程 Time Limit: 60 Sec Memory Limit: 512 MB Submit: 1697 Solved: 718 [Submit][Stat ...
- [bzoj3611][Heoi2014]大工程
[bzoj3611][Heoi2014]大工程 标签: 虚树 DP 题目链接 题解 发现\(\sum k与n\)是同阶的,很容易想到虚树. 那么难点就在dp统计上了. 对于和的话,dp[u]表示u子树 ...
- BZOJ 3611: [Heoi2014]大工程 [虚树 DP]
传送门 题意: 多次询问,求最长链最短链链总长 煞笔$DP$记录$d,c,f,g$ $MD$该死拍了一下午没问题然后交上去就$T$ 然后发现树链剖分写成$size[v]+=size[u]$ 我想知道我 ...
- 2021年全球十大工程成就,中国有几个? | 科技袁人
来源: 风云之声 视频链接: 西瓜视频: https://www.ixigua.com/7068180516549329415 本视频发布于2021年2月25日,观看量已达7.4万次 精彩呈现: 20 ...
- 《Engineering》评选2021年全球十大工程成就 | 中国工程院院刊
来源:风云之声 "2021全球十大工程成就"发布 工程是现实的.直接的生产力,是人类改变世界的重要活动.古往今来,人类创造了众多令人惊叹的工程成就,持续带动着经济发展和社会的深刻变 ...
- 《Engineering》评选2021年全球十大工程成就
来源:中国工程院院刊 "2021全球十大工程成就"发布 工程是现实的.直接的生产力,是人类改变世界的重要活动.古往今来,人类创造了众多令人惊叹的工程成就,持续带动着经济发展和社会的 ...
- 从复现人类智能到挑战AI大工程,智能计算正经历什么考验?
来源:AI科技评论 作者:杏花 编辑:青暮 世界顶级机器学习专家Michael I.Jordan曾提出一个观点,他认为人工智能正逐步由原理性研究,走向人工智能大工程. Michael I.Jordan ...
- YouTube深度学习推荐系统的十大工程问题
文 | 王喆 源 | https://zhuanlan.zhihu.com/p/52504407 这篇文章主要介绍了YouTube深度学习系统论文中的十个工程问题,为了方便进行问题定位,我们还是简单介 ...
最新文章
- Foundation 框架
- 再谈HTTP2性能提升之背后原理—HTTP2历史解剖
- .net之 datagrid
- povray[1] = 天空
- php基本功之_get(),_set()的用法
- 计算机控制z反变换公式,第三章 计算机控制系统的数学描述(修正Z变换).ppt
- [转载] numpy.reshape用法(自用)
- CentOS6.4 X86_64 kvm+PXE备忘
- 关于idea中运行maven项目报错显示找不到包或符号的问题——终极方案
- JAVA笔试题常见坑_java笔试常见的选择题(坑你没商量)
- 扫雷游戏网页版_借“买量”造爆款,梦幻西游网页版击穿H5游戏天花板
- 8000401a 因为配置标识不正确,系统无法开始服务器进程。请检查用户名和密码。
- 如何使用 JavaScript 快速构建一个二维码生成器
- 基于OpenCv的人脸识别系统设计
- Odin Inspector 系列教程 --- 初识Odin序列化
- html表头固定原理,html Table 表头固定的实现
- winpe装linux系统下载,winpe 安装linux
- python3 题解(33 人民币金额大写)
- 微擎we7模块和模板安装方法
- GBK,UTF8是什么?
热门文章
- 网站发布后验证码不显示
- (转)Scala中协变(+)、逆变(-)、上界(:)、下界(:)简单介绍
- Linux程序包管理和yum用法
- BFS(双向) HDOJ 3085 Nightmare Ⅱ
- Spark源码系列(一)spark-submit提交作业过程
- Android之多种Bitmap效果
- Lambda 表达式入门,这篇够了!
- Myeclipse 2020.5 版本首发!支持 Java14
- Spring Cloud 2020 年路线图
- Java会走向晦暗吗?Kotlin会取而代之吗