树的重心,树形$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的更多相关文章

  1. hdu 4912 Paths on the tree(树链拆分+贪婪)

    题目链接:hdu 4912 Paths on the tree 题目大意:给定一棵树,和若干个通道.要求尽量选出多的通道,而且两两通道不想交. 解题思路:用树链剖分求LCA,然后依据通道两端节点的LC ...

  2. (hdu)5423 Rikka with Tree (dfs)

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5423 Problem Description As we know, Rikka is p ...

  3. 【hdu 6161】Big binary tree(二叉树、dp)

    多校9 1001 hdu 6161 Big binary tree 题意 有一个完全二叉树.编号i的点值是i,操作1是修改一个点的值为x,操作2是查询经过点u的所有路径的路径和最大值.10^5个点,1 ...

  4. 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 ...

  5. hdu 5534 (完全背包) Partial Tree

    题目:这里 题意: 感觉并不能表达清楚题意,所以 Problem Description In mathematics, and more specifically in graph theory, ...

  6. 【HDU 4408】Minimum Spanning Tree(最小生成树计数)

    Problem Description XXX is very interested in algorithm. After learning the Prim algorithm and Krusk ...

  7. 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 ...

  8. 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 ...

  9. HDU - 5156 Harry and Christmas tree

    题目链接 : http://acm.hdu.edu.cn/showproblem.php?pid=5156 题意 : 给一颗编号为1-n的以1为根的树, 已知有m个颜色的礼物分布在某些节点上(同一节点 ...

随机推荐

  1. Elastic Search操作入门

    前言 Elastic Search是基于Lucene这个非常成熟的索引方案,另加上一些分布式的实现:集群,sharding,replication等.具体可以参考我同事写的文章. 本文主要介绍ES入门 ...

  2. 51nod 1170 1770 数数字(数学技巧)

    解题思路:看到题后,直接想到分成两种情况: ①:a*b >9 这里又分成两种 1. n==1 a*b 直接是一个两位数 求得十位和个位(这里十位和个位不可能相等) 然后如果等于d 则结果=1 2 ...

  3. [Luogu 1160] 队列安排

    Luogu 1160 队列安排 链表H2O H2O H2O模板. 太久不写链表,忘干净了,竟调了半个晚上. 保留备用. #include <cstdio> #include <cst ...

  4. 32岁白发菜鸟拿2.6万年薪苦熬10年 NBA首秀便惊艳世人 科比书豪纷纷为他点赞

    这是一场普通的常规赛——斯台普斯球馆,湖人的赛季第81场.比赛的结果也没什么意外:客场作战的火箭106-99带走胜利.然而,这一场的斯台普斯却成了欢乐的海洋,现场甚至喊出了MVP的呼声,这份赞誉,送给 ...

  5. Java 必看的 Spring 知识汇总

    Spring框架是由于软件开发的复杂性而创建的.Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情.然而,Spring的用途不仅仅限于服务器端的开发.从简单性.可测试性和松耦 ...

  6. 【BZOJ4870】组合数问题 [矩阵乘法][DP]

    组合数问题 Time Limit: 10 Sec  Memory Limit: 512 MB[Submit][Status][Discuss] Description Input 第一行有四个整数 n ...

  7. NGINX: 反向代理 Nexus

    Nginx 反向代理 nexus 的服务, 一直卡在 Initialize... 解决方式是添加一个 header X-Forwarded-Proto: proxy_set_header X-Forw ...

  8. Gulp、Grunt构建工具

    在Gulp中创建一个库从磁盘gulp.src读取源文件并通过磁盘管道写回内容到gulp.dest,可以理解成只是将文件复制到另一个目录. var gulp = require('gulp'); gul ...

  9. Nodejs mac版安装

    Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven ...

  10. Python ctypes 在 Python 2 和 Python 3 中的不同 // 使用ctypes过程中问题汇总

    In Python 2.7, strings are byte-strings by default. In Python 3.x, they are unicode by default. Try ...