@description@

众所周知小G热衷于搏弈,有一天他来到你的大草原上,抢走了你所有的牛羊,以供他搏弈。

你大惊失措,赶紧来到小G家拯救你的牛羊,然而,当你赶到的时候,你的牛已经变成了搏弈牛,你的羊已经变成了搏弈羊。你怒不可遏,决定拆了小G的家。

小G的家有 n 个房间,n−1 条走廊连接这些房间使得房间之间两两可达。在每一间房间里可能有一只牛,或者一只羊,或者一只小G,注意由于小G会分身术,所以可以有多个小G。

经过慎重考虑,你决定选择一些房间来攻击,你选择的房间必须满足两两之间可以不通过你未选择的房间到达。当你攻击时,你选择的房间中的所有牛、羊和小G都会来与你搏弈,由于人的力量是有限的,你只能应对 A 只牛,B 只羊,C 只小G。也就是说你能够同时应对 u 只牛,v 只羊和 w 只小G当且仅当 u≤A 且 v≤B 且 w≤C。

你想知道有多少种选择房间的方案使得你可以应对他们,输出其对 998244353 取模的结果。

@Input format@

第一行四个数 n,A,B,C,含义如题。

第二行 n 个数,第 i 个数表示第 i 间房里是什么:0 代表牛,1 代表羊,2 代表小G。

接下来 n−1 行,每行两个数 u,v,表示 u 到 v 之间有一条走廊。

@Output format@

一个数表示答案。

@Sample input@

5 1 1 1

0 1 0 0 2

1 2

1 3

3 4

4 5

@Sample output@

7

@Constraints@

对于所有的数据,n≤200,A+B+C≤n/2。

@solution@

任轩笛的论文《解决树上连通块问题的一些技巧和工具》中有提到与这道题类似的题并给出了解决方案:

对于一类树上连通块DP问题,如果信息的合并不够高效,但加入单点的信息比较高效,往往可以按照DFS序转移,把合并子树变成添加单点。

先假定选出的连通块必须包含根,求出整棵树的DFS序,一个包含根的树上连通块的结构一定形如整棵树去掉若干个互不相交的子树。在DFS序中,去掉的就是连续的若干段。

设 dp[i] 表示考虑了DFS序前 i 个节点时的信息。如果要选择第 i 个节点,则转移到 dp[i+1],否则转移到 dp[j],其中 j 是第 i 个点子树DFS序的右端点+1,表示去掉这整个子树。

而对于选出的连通块可以不包含根的问题,只要进行点分治,每次把重心作为根,算

出强制包含重心的方案数,再把重心删除,对每个连通块递归做。

之后论文中给出的例题也与这道题大同小异。

题意:给出一棵树,每个点有个颜色。给出3种颜色 u, v, w ,求有多少个树上连通块满足里面颜色为 u, v, w 的点的个数分别为 a, b, c 。

做法:用 dp[x][i][j][k] 表示处理了以 x 为根的子树,三种颜色个数分别为 i, j, k 的方案数。如果使用三维FFT优化,复杂度能变成 O(nabc log abc) ,但是常数和码量都较大。考虑使用上述的点分治算法,配合按DFS序转移,复杂度为 O(nabc log n)。

然后论文的题解基本照搬过来即可。

因为 A + B + C <= n/2 <= 100,所以 A*B*C 最大时 A = B = C,可以得到 A*B*C 最大约可以取 3*10^4。

所以 O(nABC*logn) 是可以跑得过的。

所以这是一道论文题。

@accepted code@

#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 200;
const int MOD = 998244353;
struct edge{
int to; edge *nxt;
}edges[2*MAXN + 5], *adj[MAXN + 5], *ecnt=&edges[0];
void addedge(int u, int v) {
edge *p = (++ecnt);
p->to = v, p->nxt = adj[u], adj[u] = p;
p = (++ecnt);
p->to = u, p->nxt = adj[v], adj[v] = p;
}
int siz[MAXN + 5], hvy[MAXN + 5], dfn[MAXN + 5], dcnt;
int a[MAXN + 5], n, A, B, C;
bool vis[MAXN + 5];
void dfs(int x, int fa) {
dfn[++dcnt] = x, siz[x] = 1, hvy[x] = 0;
for(edge *p=adj[x];p;p=p->nxt) {
if( vis[p->to] || p->to == fa ) continue;
dfs(p->to, x);
siz[x] += siz[p->to];
hvy[x] = max(hvy[x], siz[p->to]);
}
}
int GetG(int x, int fa, int tot) {
int ret = x; hvy[x] = max(hvy[x], tot - siz[x]);
for(edge *p=adj[x];p;p=p->nxt) {
if( vis[p->to] || p->to == fa ) continue;
int tmp = GetG(p->to, x, tot);
if( hvy[tmp] < hvy[ret] )
ret = tmp;
}
return ret;
}
int dp[MAXN + 5][34*34*35 + 5], ans = 0;
inline int id(int x, int y, int z) {
return x*(B+1)*(C+1) + y*(C+1) + z;
}
void divide(int x) {
vis[x] = true, dcnt = 0, dfs(x, -1);
for(int p=1;p<=dcnt+1;p++)
for(int i=0;i<=A;i++)
for(int j=0;j<=B;j++)
for(int k=0;k<=C;k++)
dp[p][id(i, j, k)] = 0;
dp[1][id(0, 0, 0)] = 1;
for(int p=1;p<=dcnt;p++)
for(int i=0;i<=A;i++)
for(int j=0;j<=B;j++)
for(int k=0;k<=C;k++) {
dp[p+siz[dfn[p]]][id(i, j, k)] = (dp[p+siz[dfn[p]]][id(i, j, k)] + dp[p][id(i, j, k)])%MOD;
if( a[dfn[p]] == 0 && i != A ) dp[p+1][id(i+1, j, k)] = (dp[p+1][id(i+1, j, k)] + dp[p][id(i, j, k)])%MOD;
if( a[dfn[p]] == 1 && j != B ) dp[p+1][id(i, j+1, k)] = (dp[p+1][id(i, j+1, k)] + dp[p][id(i, j, k)])%MOD;
if( a[dfn[p]] == 2 && k != C ) dp[p+1][id(i, j, k+1)] = (dp[p+1][id(i, j, k+1)] + dp[p][id(i, j, k)])%MOD;
}
for(int i=0;i<=A;i++)
for(int j=0;j<=B;j++)
for(int k=0;k<=C;k++)
ans = (ans + dp[dcnt + 1][id(i, j, k)])%MOD;
ans = (ans + MOD - 1)%MOD;
for(edge *p=adj[x];p;p=p->nxt)
if( !vis[p->to] ) divide(GetG(p->to, -1, siz[p->to]));
}
int main() {
scanf("%d%d%d%d", &n, &A, &B, &C);
for(int i=1;i<=n;i++)
scanf("%d", &a[i]);
for(int i=1;i<n;i++) {
int u, v; scanf("%d%d", &u, &v);
addedge(u, v);
}
dcnt = 0, dfs(1, -1), divide(GetG(1, -1, siz[1]));
printf("%d\n", ans);
}

@details@

所以多读书论文是有好处的。

只不过我估计 noi 上是不会出现这种题的吧。。。

@noi.ac - 442@ 牛羊被他抢了的更多相关文章

  1. # NOI.AC省选赛 第五场T1 子集,与&最大值

    NOI.AC省选赛 第五场T1 A. Mas的童年 题目链接 http://noi.ac/problem/309 思路 0x00 \(n^2\)的暴力挺简单的. ans=max(ans,xor[j-1 ...

  2. NOI.ac #31 MST DP、哈希

    题目传送门:http://noi.ac/problem/31 一道思路好题考虑模拟$Kruskal$的加边方式,然后能够发现非最小生成树边只能在一个已经由边权更小的边连成的连通块中,而树边一定会让两个 ...

  3. NOI.AC NOIP模拟赛 第五场 游记

    NOI.AC NOIP模拟赛 第五场 游记 count 题目大意: 长度为\(n+1(n\le10^5)\)的序列\(A\),其中的每个数都是不大于\(n\)的正整数,且\(n\)以内每个正整数至少出 ...

  4. NOI.AC NOIP模拟赛 第六场 游记

    NOI.AC NOIP模拟赛 第六场 游记 queen 题目大意: 在一个\(n\times n(n\le10^5)\)的棋盘上,放有\(m(m\le10^5)\)个皇后,其中每一个皇后都可以向上.下 ...

  5. NOI.AC NOIP模拟赛 第二场 补记

    NOI.AC NOIP模拟赛 第二场 补记 palindrome 题目大意: 同[CEOI2017]Palindromic Partitions string 同[TC11326]Impossible ...

  6. NOI.AC NOIP模拟赛 第一场 补记

    NOI.AC NOIP模拟赛 第一场 补记 candy 题目大意: 有两个超市,每个超市有\(n(n\le10^5)\)个糖,每个糖\(W\)元.每颗糖有一个愉悦度,其中,第一家商店中的第\(i\)颗 ...

  7. NOI.AC NOIP模拟赛 第四场 补记

    NOI.AC NOIP模拟赛 第四场 补记 子图 题目大意: 一张\(n(n\le5\times10^5)\)个点,\(m(m\le5\times10^5)\)条边的无向图.删去第\(i\)条边需要\ ...

  8. NOI.AC NOIP模拟赛 第三场 补记

    NOI.AC NOIP模拟赛 第三场 补记 列队 题目大意: 给定一个\(n\times m(n,m\le1000)\)的矩阵,每个格子上有一个数\(w_{i,j}\).保证\(w_{i,j}\)互不 ...

  9. NOI.AC WC模拟赛

    4C(容斥) http://noi.ac/contest/56/problem/25 同时交换一行或一列对答案显然没有影响,于是将行列均从大到小排序,每次处理限制相同的一段行列(呈一个L形). 问题变 ...

随机推荐

  1. GIT → 02:Git和Svn比较

    2.1 SVN介绍 2.1.1 SVN简介 SVN 属于集中式版本管理控制系统,服务器中保存了所有文件的不同版本,而协同工作人员通过连接svn服务器,提取出最新的文件,获取提交更新.Subversio ...

  2. LAMP标准化安装

    操作系统说明: 操作系统 版本 linux red hat release 6.4 关键软件包说明: 软件包 版本 目录 运行用户 httpd-2.2.27.tar.gz 2.2.27 /usr/lo ...

  3. 五.反馈(Hopfield)神经网络

    前馈网络一般指前馈神经网络或前馈型神经网络.它是一种最简单的神经网络,各神经元分层排列.每个神经元只与前一层的神经元相连.接收前一层的输出,并输出给下一层,数据正想流动,输出仅由当前的输入和网络权值决 ...

  4. json原生解析

    身为新手,在运用网络解析json数据的时候,发现先会用Gson等框架解析json,然后就懒起来学原生解析了,这下在看别人写的demo的时候就尴尬了,一块块的,不懂写什么,气氛十分尴尬. 不多说,先来条 ...

  5. listview显示固定条数

    看了很多网上其他大神的,感觉还是在listview的adapter中的getCount中下手比较好点 毕竟计算高度等等,那会让辅助的布局会一团糟,例如下面的搜索历史只显示四条,布局中有横向listvi ...

  6. 7. 18 test 砍树题解

    (题面保密,内部人员可览) 首先观察题面,可得出如下公式 ∑(ceil(a[i] /d)*d−a[i])≤k 其中,ceil(a[i] /d)表示在需要被砍伐之前所经过的轮数,ceil函数是为了保证一 ...

  7. 数据挖掘案例:基于 ReliefF和K-means算法的应用

    数据挖掘案例:基于 ReliefF和K-means算法的应用 数据挖掘方法的提出,让人们有能力最终认识数据的真正价值,即蕴藏在数据中的信息和知识.数据挖掘(DataMiriing),指的是从大型数据库 ...

  8. vue+axios 对restful 请求封装

    礼拜天来公司整理项目,项目是最近开始重构的,里面的各种http请求接口是restful结构的(为了提升项目的比格),整理一下笔记 [restful介绍][1]博主讲的很详细 技术栈: vue + vu ...

  9. day38 17-Spring的Bean的属性注入:注解方式

    这个类已经可以由Spring控制反转了,那么属性呢?属性分为普通属性和对象属性两部分. JSR是一个组织,和W3C一样是定义一些标准的.它里面也定义了一歌注解,Spring对这个注解也是支持的.其实这 ...

  10. ORACLE 日常维护命令手册

    1查看数据库版本SELECT * FROM V$VERSION; 2查看数据库语言环境SELECT USERENV('LANGUAGE') FROM DUAL; 3查看ORACLE实例状态SELECT ...