3611: [Heoi2014]大project|树形DP|虚树
构建出虚树然后DP统计答案 
自己写的DP太傻QAQ,各种WA 
膜了一发PoPoQQQ大爷的DP方法 
mxdis,mndis分别表示到当前点近期和最远的被选出来的点的距离 
mx,mn分别表示在以当前点为根的情况下距离最远的两点的距离和距离近期的两点的距离。 
sum表示在以当前点为根的子树中,全部关键的到当前点的距离之和 
c数组表示以当前点为根的子树中。关键点的个数 
然后我用了个时间戳来标记关键点
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
#include<set>
#include<map>
#define inf 0x7FFFFFFF
#define ll long long
#define N 1000005
using namespace std;
int sc()
{
    int i=0,f=1; char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();
    return i*f;
}
ll mx[N],mn[N],mn_dis[N],mx_dis[N],c[N],sum[N],ans;
int Head[N],Nxt[N],Lst[N];
int a[N],st[N],tim[N];
int size[N],deep[N],fa[N],S[N],top[N];
int head[N],lst[N<<1],nxt[N<<1],v[N<<1];
int n,tot,cnt,Tot,TI;
void Insert(int x,int y)
{
    Lst[++Tot]=y;Nxt[Tot]=Head[x];Head[x]=Tot;
}
void insert(int x,int y)
{
    lst[++tot]=y;nxt[tot]=head[x];head[x]=tot;
    lst[++tot]=x;nxt[tot]=head[y];head[y]=tot;
}
void dfs(int x,int f)
{
    size[x]=1;
    for(int i=head[x];i;i=nxt[i])
        if(lst[i]!=f)
        {
            deep[lst[i]]=deep[x]+1;
            fa[lst[i]]=x;
            dfs(lst[i],x);
            size[x]+=size[lst[i]];
        }
}
void _dfs(int x,int htp)
{
    int k=0;top[x]=htp;S[x]=++cnt;
    for(int i=head[x];i;i=nxt[i])
        if(lst[i]!=fa[x]&&size[lst[i]]>size[k])k=lst[i];
    if(!k)return;_dfs(k,htp);
    for(int i=head[x];i;i=nxt[i])
        if(lst[i]!=k&&lst[i]!=fa[x])
            _dfs(lst[i],lst[i]);
}
int Lca(int x,int y)
{
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]])swap(x,y);
        x=fa[top[x]];
    }
    return deep[x]<deep[y]?
x:y;
}
bool cmp(int x,int y){return S[x]<S[y];}
ll dis(int x,int y)
{
    return deep[x]+deep[y]-2*deep[Lca(x,y)];
}
void dp(int x)
{
    c[x]=tim[x]==TI;sum[x]=0;
    mx_dis[x]=tim[x]==TI?0:-inf;
    mn_dis[x]=tim[x]==TI?0:inf;
    mn[x]=inf;mx[x]=-inf;
    for(int i=Head[x];i;i=Nxt[i])
    {
        ll d=dis(Lst[i],x); dp(Lst[i]);
        ans+=sum[x]*c[Lst[i]]+(sum[Lst[i]]+c[Lst[i]]*d)*c[x];
        c[x]+=c[Lst[i]];
        sum[x]+=sum[Lst[i]]+c[Lst[i]]*d;
        mx[x]=max(mx[x],max(mx[Lst[i]],mx_dis[Lst[i]]+d+mx_dis[x]));
        mn[x]=min(mn[x],min(mn[Lst[i]],mn_dis[Lst[i]]+d+mn_dis[x]));
        mx_dis[x]=max(mx_dis[x],mx_dis[Lst[i]]+d);
        mn_dis[x]=min(mn_dis[x],mn_dis[Lst[i]]+d);
    }
    Head[x]=0;
}
void solve()
{
    int n=sc(),top=0;Tot=0;TI++;
    for(int i=1;i<=n;i++)
        tim[a[i]=sc()]=TI;
    sort(a+1,a+n+1,cmp);
    if(a[1]!=1)st[++top]=1;
    for(int i=1;i<=n;i++)
    {
        int t=a[i],f=0;
        while(top)
        {
            f=Lca(st[top],t);
            if(top>1&&deep[f]<deep[st[top-1]]) Insert(st[top-1],st[top]),top--;
            else if(deep[f]<deep[st[top]]){Insert(f,st[top]);top--;break;}
            else break;
        }
        if(st[top]!=f&&f)st[++top]=f;
        st[++top]=t;
    }
    while(--top)Insert(st[top],st[top+1]);
    ans=0;dp(1);
    printf("%lld %lld %lld\n",ans,mn[1],mx[1]);
}
int main()
{
    n=sc();
    for(int i=1;i<n;i++)
    {
        int x=sc(),y=sc();
        insert(x,y);
    }
    dfs(1,0);_dfs(1,1);
    for(int i=1,m=sc();i<=m;i++)
        solve();
    return 0;
}
3611: [Heoi2014]大project|树形DP|虚树的更多相关文章
- BZOJ3611:[HEOI2014]大工程(树形DP,虚树)
		
Description 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上. 在 2 个国家 a,b 之间建一条新通 ...
 - [BZOJ3611] [Heoi2014]大工程(DP + 虚树)
		
传送门 $dp[i][0]$表示节点i到子树中的所有点的距离之和 $dp[i][1]$表示节点i到子树中最近距离的点的距离 $dp[i][2]$表示节点i到子树中最远距离的点的距离 建好虚树后dp即可 ...
 - 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分
		
树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...
 - 【CF809E】Surprise me! 树形DP 虚树 数学
		
题目大意 给你一棵\(n\)个点的树,每个点有权值\(a_i\),\(a\)为一个排列,求 \[ \frac{1}{n(n-1)}\sum_{i=1}^n\sum_{j=1}^n \varphi(a_ ...
 - CF613D:Kingdom and its Cities(树形DP,虚树)
		
Description 一个王国有n座城市,城市之间由n-1条道路相连,形成一个树结构,国王决定将一些城市设为重要城市. 这个国家有的时候会遭受外敌入侵,重要城市由于加强了防护,一定不会被占领.而非重 ...
 - BZOJ2286:[SDOI2011]消耗战(树形DP,虚树)
		
Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总部在编号为1的岛屿,而且他们已经没有足够多的能源维系战斗,我军 ...
 - 3611: [Heoi2014]大工程
		
3611: [Heoi2014]大工程 链接 分析: 树形dp+虚树. 首先建立虚树,在虚树上dp. dp:sum[i]为i的子树中所有询问点之间的和.siz[i]为i的子树中有多少询问点,mn[i] ...
 - bzoj 3611 [Heoi2014]大工程(虚树+DP)
		
3611: [Heoi2014]大工程 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 408 Solved: 190[Submit][Status] ...
 - HDU 4514 - 湫湫系列故事——设计风景线 - [并查集判无向图环][树形DP求树的直径]
		
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4514 Time Limit: 6000/3000 MS (Java/Others) Memory Li ...
 
随机推荐
- 电子书下载:Delphi XE 5 移动开发入门手册(完整版)
			
更多电子书请到: http://maxwoods.400gb.com 下载:Delphi XE5移动开发入门手册(完整版)
 - Delphi 包的设计思想及它与PAS、BPL、DCU、DLL、OXC的关系
			
一.Delphi中各种文件的介绍,及其关系. OXC: ActiveX控件.会被安装到某一个组件包DPK中,在Imports中会创建PAS.DCU.DCR三个文件. DLL: 动态链接库文件,它的Ex ...
 - javascript 原型继承
			
因为javascript没有专门的机制去实现类,所以这里只能是借助它的函数能够嵌套的机制来模拟实现类.在javascript中,一个函数,可以包含变量,也可以包含其它的函数,那么,这样子的话,我们就可 ...
 - Oracle Apps DBA R12.2 Syllabus
			
1. What is Oracle R12.2 R12.2 Definition Architecture Advantages of R12.2 Limitations of R12.2 What ...
 - android 玩转ContentProvider之二--实现多个ContentProvider对多张表进行操作
			
SQLite数据库直接操作类: DatabaseHelper.java package com.jacp.database; import android.content.Context; impor ...
 - java如何直接返回excel到客户端
			
既然是web项目首先你得拿到响应才能向外部写出,你得拿到响应对象response,1.添加如下两行代码response.setContentType("application/vnd..ms ...
 - 寂静之地百度云在线观看迅雷下载A Quiet Place高清BT下载
			
原名:A Quiet Place 地区:美国 语言:英语 / 美国手语 首播:2018-05-18(中国大陆) / 2018-03-09(西南偏南电影节) / 2018-04-06(美国) 电视台 ...
 - UVA 1508 - Equipment 状态压缩 枚举子集 dfs
			
UVA 1508 - Equipment 状态压缩 枚举子集 dfs ACM 题目地址:option=com_onlinejudge&Itemid=8&category=457& ...
 - 《Python计算机视觉编程》
			
<Python计算机视觉编程> 基本信息 作者: (美)Jan Erik Solem 译者: 朱文涛 袁勇 丛书名: 图灵程序设计丛书 出版社:人民邮电出版社 ISBN:978711535 ...
 - 在SQLite中使用事务
			
使用SQLiteDatabase的beginTransaction()方法可以开启一个事务,程序执行到endTransaction() 方法时会检查事务的标志是否为成功,如果为成功则提交事务,否则回滚 ...