HDU 4863 Centroid of a Tree
树的重心,树形$dp$,背包。
树的重心有两个充分必要条件:
$1$.某树有两个重心$a$,$b$ $<=>$ $a$与$b$相邻,断开$a$与$b$之间的边之后,两个联通分量内的点的个数相同。
$2$.某树有一个重心$a$ $<=>$ 以$a$为根的树,去掉a之后,剩下的联通分量,除去节点个数最多的联通分量后,剩余的联通分量节点个数之和大于等于最大的联通分量的节点个数。
因此,可以先计算出初始树的重心,分两种情况讨论。
如果有两个重心$a$,$b$,那么,我们需要计算出断开$a$,$b$之间的边,以$a$为根的树以及以$b$为根的树中包含$x$个节点的树有几种,然后枚举$x$两边相乘求和就是答案了。
如果只有一个重心$a$,这种情况比两个重心的复杂一点,需要计算以$a$为根的树有多少种满足充要条件$2$,先要计算出以$a$的儿子为根的树中包含$x$个节点的树有几种,然后再用背包去算一下反面的情况,总的方案减去反面的就是答案。
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<ctime>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0);
void File()
{
freopen("D:\\in.txt","r",stdin);
freopen("D:\\out.txt","w",stdout);
}
template <class T>
inline void read(T &x)
{
char c = getchar();
x = ;
while(!isdigit(c)) c = getchar();
while(isdigit(c))
{
x = x * + c - '';
c = getchar();
}
} int T,n;
int mod=;
int dp[][];
int c[],mx[],k[],f[];
vector<int>tmp[],t[],zx; void init()
{
memset(dp,,sizeof dp);
memset(c,,sizeof c);
memset(mx,,sizeof mx);
memset(f,,sizeof f);
for(int i=;i<=n;i++) tmp[i].clear();
for(int i=;i<=n;i++) t[i].clear();
zx.clear();
} void D(int x)
{
f[x]=;
for(int i=;i<tmp[x].size();i++)
{
if(f[tmp[x][i]]) continue;
t[x].push_back(tmp[x][i]);
D(tmp[x][i]);
}
} void F(int x)
{
for(int i=;i<t[x].size();i++)
{
F(t[x][i]);
mx[x]=max(mx[x],c[t[x][i]]);
c[x]=c[x]+c[t[x][i]];
}
c[x]++;
} void G(int x)
{
f[x]=;
for(int i=;i<tmp[x].size();i++)
{
if(f[tmp[x][i]]) continue;
if(zx.size()==&&tmp[x][i]==zx[]) continue;
t[x].push_back(tmp[x][i]);
G(tmp[x][i]);
}
} void DP(int x)
{
dp[x][]=; int h[],g[];
memset(h,,sizeof h); memset(g,,sizeof g);
g[]=;
for(int i=;i<t[x].size();i++)
{
DP(t[x][i]);
for(int j=;j<=c[x]+c[t[x][i]];j++) h[j]=;
for(int p1=c[x];p1>=;p1--)
for(int p2=c[t[x][i]];p2>=;p2--)
h[p1+p2]=(h[p1+p2]+g[p1]*dp[t[x][i]][p2]%mod)%mod;
for(int j=;j<=c[x]+c[t[x][i]];j++) g[j]=h[j]; c[x]=c[x]+c[t[x][i]];
}
c[x]++;
for(int i=;i<=;i++) dp[x][i]=g[i-];
} int main()
{
scanf("%d",&T); int cas=;
while(T--)
{
scanf("%d",&n);
init();
for(int i=;i<=n-;i++)
{
int x,y; scanf("%d%d",&x,&y);
tmp[x].push_back(y);
tmp[y].push_back(x);
}
D(); F(); for(int i=;i<=n;i++) k[i]=max(mx[i],n-c[i]);
int mn=; for(int i=;i<=n;i++) mn=min(mn,k[i]);
for(int i=;i<=n;i++) if(k[i]==mn) zx.push_back(i); for(int i=;i<=n;i++) t[i].clear();
memset(f,,sizeof f);
G(zx[]); if(zx.size()==) G(zx[]); memset(c,,sizeof c);
DP(zx[]); if(zx.size()==) DP(zx[]); printf("Case %d: ",cas++); int ans=;
if(zx.size()==)
{
int h[],g[]; int fm=;
for(int i=;i<t[zx[]].size();i++)
{
memset(h,,sizeof h); memset(g,,sizeof g); g[]=;
int a=;
for(int j=;j<t[zx[]].size();j++)
{
if(i==j) continue;
for(int w=;w<=a+c[t[zx[]][j]];w++) h[w]=;
for(int p1=a;p1>=;p1--)
for(int p2=c[t[zx[]][j]];p2>=;p2--)
h[p1+p2]=(h[p1+p2]+g[p1]*dp[t[zx[]][j]][p2]%mod)%mod;
a=a+c[t[zx[]][j]];
for(int j=;j<=;j++) g[j]=h[j];
} for(int j=;j<=c[t[zx[]][i]];j++)
for(int w=;w<j;w++)
fm=(fm+dp[t[zx[]][i]][j]*g[w]%mod)%mod;
}
for(int i=;i<=n;i++) ans=(ans+dp[zx[]][i])%mod;
printf("%d\n",(ans-fm+mod)%mod); }
else
{
for(int i=;i<=;i++)
ans=(ans+dp[zx[]][i]*dp[zx[]][i]%mod)%mod;
printf("%d\n",ans);
} }
return ;
}
HDU 4863 Centroid of a Tree的更多相关文章
- hdu 4912 Paths on the tree(树链拆分+贪婪)
题目链接:hdu 4912 Paths on the tree 题目大意:给定一棵树,和若干个通道.要求尽量选出多的通道,而且两两通道不想交. 解题思路:用树链剖分求LCA,然后依据通道两端节点的LC ...
- (hdu)5423 Rikka with Tree (dfs)
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5423 Problem Description As we know, Rikka is p ...
- 【hdu 6161】Big binary tree(二叉树、dp)
多校9 1001 hdu 6161 Big binary tree 题意 有一个完全二叉树.编号i的点值是i,操作1是修改一个点的值为x,操作2是查询经过点u的所有路径的路径和最大值.10^5个点,1 ...
- HDU 6191 Query on A Tree(可持久化Trie+DFS序)
Query on A Tree Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Othe ...
- hdu 5534 (完全背包) Partial Tree
题目:这里 题意: 感觉并不能表达清楚题意,所以 Problem Description In mathematics, and more specifically in graph theory, ...
- 【HDU 4408】Minimum Spanning Tree(最小生成树计数)
Problem Description XXX is very interested in algorithm. After learning the Prim algorithm and Krusk ...
- Hdu.1325.Is It A Tree?(并查集)
Is It A Tree? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) To ...
- hdu 1325 Is It A Tree?
Is It A Tree? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) To ...
- HDU - 5156 Harry and Christmas tree
题目链接 : http://acm.hdu.edu.cn/showproblem.php?pid=5156 题意 : 给一颗编号为1-n的以1为根的树, 已知有m个颜色的礼物分布在某些节点上(同一节点 ...
随机推荐
- 应用Xml.Linq读xml文件
c#提供了System.Xml.Linq操作xml文件,非常方便,本文主要介绍如何应用System.Xml.Linq读取xml文件. xml文本 <?xml version="1.0& ...
- Flume入门——Selector、Chanel等
1.selector (http://blog.csdn.net/looklook5/article/details/40430965) (http://blog.csdn.net/xiao_jun_ ...
- dp优化-四边形不等式(模板题:合并石子)
学习博客:https://blog.csdn.net/noiau/article/details/72514812 看了好久,这里整理一下证明 方程形式:dp(i,j)=min(dp(i,k)+dp( ...
- 【洛谷 P4008】 [NOI2003]文本编辑器 (Splay)
题目链接 \(Splay\)先练到这吧(好像还有道毒瘤的维护数列诶,算了吧) 记录下光标的编号,维护就是\(Splay\)基操了. 另外数据有坑,数据是\(Windows\)下生成了,回车是'\n\r ...
- [bzoj4567][Scoi2016]背单词-Trie+贪心+模型转化
Brief Description 给你N个互不相同的字符串,记\(S_i\)为第i个字符串,现在要求你指定N个串的出现顺序,我们用\(V_i\)表示第i个字符串是第几个出现的,则V为1到N的一个排列 ...
- 复现VGG19训练自定义图像分类
1.复现VGG训练自定义图像分类,成功了哈哈. 需要代码工程可联系博主qq号,在左边连接可找到. 核心代码: # coding:utf-8 import tensorflow as tf import ...
- javascript 事件知识集锦
1.事件委托极其应用 转载的链接: http://www.webhek.com/event-delegate/#comments 2. 解析javascript事件机制 转载链接: http: ...
- ADC 計算時,階數的選擇
reference : ADC 階數的計算
- tornado当用户输入的URL无效时转入设定的页面
今天做web的测验..坑爹的要用tornado...作为一个比较新的用的人还不多的东东...查资料好麻烦.. 下面是当用户输入非法 url时, 显示一个自定义 404 页面提示用户,其访问的页面不存在 ...
- 网站服务器压力Web性能测试(3):http_load:测试web服务器的吞吐量与负载
1.http_load是国外一个博主写的一个基于Linux的性能测工具,小巧轻便,解压缩后不到100k,下载安装方法: wget https://acme.com/software/http_load ...