【洛谷4815】[CCO2014] 狼人游戏(树形DP)
大致题意: 已知有平民和狼人共\(n\)个,每个平民会指控和保护任何人,每个狼人只会指控平民、保护狼人。告诉你\(m\)对指控与保护的关系,求有\(k\)个狼人的方案总数。
树形\(DP\)
这题目乍看很神仙,但一看给出的其他一些限制,就可以发现这就是一棵树!
而对于这种问题,容易想到用树形\(DP\)去求解。
我们可以设\(f_{i,0/1,j,0/1}\)来表示编号为\(i\)的节点作为平民/狼人时共有\(j\)个狼人的方案数,其中第二维分别表示上一次和这一次的答案,用了滚存。
则显然可以推得\(DP\)方程如下:
\]
\]
对于第一个方程,我们知道平民会指控和保护任何人,因此无论子节点为平民还是狼人都可以转移。
对于第二个方程,我们知道狼人只会指控平民、保护狼人,因此当指控关系时子节点必须为平民,当保护关系时子节点必须为狼人。
统计答案
由于这是一片森林,因此我们最后还需要统计答案,而这也是一个类似的过程。
我们可以设\(s_{0/1,j}\)来表示共有\(j\)个狼人的方案数,其中第一维类似于前面的第二位,分别表示上一次和这一次的答案。
若我们从\(0\)号节点向所有根节点连边,则转移式其实是几乎一样的:
\]
其实很好理解,这与上面的式子就少了枚举当前节点是平民还是狼人,而\(0\)号节点作为虚拟节点,显然都不是嘛。。。
具体实现详见代码。
代码
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<tepename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define RC Reg char
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 200
#define X 1000000007
#define min(x,y) ((x)>(y)?(x):(y))
#define add(x,y,v) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y,e[ee].op=v)
#define Inc(x,y) ((x+=(y))>=X&&(x-=X))
using namespace std;
int n,m,k,ee,deg[N+5],lnk[N+5];struct edge {int to,nxt;char op;}e[N+5];
I int XSum(RI x,CI y) {return x+y>=X?x+y-X:x+y;}
class TreeDper//树形DP
{
private:
int s[2][N+5],t[N+5],g[N+5],f[N+5][2][N+5][2];
I void DP(CI x)//DP
{
g[x]=f[x][0][0][0]=f[x][0][1][1]=1;for(RI i=lnk[x],j,l,op=1;i;i=e[i].nxt,op^=1)//初始化信息,枚举子节点
{
for(memset(f[x][op],0,sizeof(f[x][op])),DP(e[i].to),j=min(k,g[x]);~j;--j) for(l=min(k-j,g[e[i].to]);~l;--l)//枚举状态进行转移
{
Inc(f[x][op][j+l][0],1LL*f[x][op^1][j][0]*XSum(f[e[i].to][t[e[i].to]][l][0],f[e[i].to][t[e[i].to]][l][1])%X),
Inc(f[x][op][j+l][1],1LL*f[x][op^1][j][1]*f[e[i].to][t[e[i].to]][l][e[i].op=='D']%X);
}g[x]+=g[e[i].to],t[x]^=1;//更新size
}
}
public:
I int GetAns()//与上面的过程类似
{
RI i,j,l,op=1;for(s[0][0]=1,i=lnk[0];i;i=e[i].nxt,op^=1)
for(memset(s[op],0,sizeof(s[op])),DP(e[i].to),j=k;~j;--j) for(l=min(k-j,g[e[i].to]);~l;--l)
Inc(s[op][j+l],1LL*s[op^1][j]*XSum(f[e[i].to][t[e[i].to]][l][0],f[e[i].to][t[e[i].to]][l][1])%X);
return s[op^1][k];
}
}T;
int main()
{
ios::sync_with_stdio(false);
RI i,x,y,ans=1;RC op;for(cin>>n>>k>>m,i=1;i<=m;++i) cin>>op>>x>>y,add(x,y,op),++deg[y];//读入+建边
for(i=1;i<=n;++i) !deg[i]&&add(0,i,'*');return printf("%d",T.GetAns()),0;//求解并输出
}
【洛谷4815】[CCO2014] 狼人游戏(树形DP)的更多相关文章
- 洛谷 P3177 [HAOI2015]树上染色 树形DP
洛谷 P3177 [HAOI2015]树上染色 树形DP 题目描述 有一棵点数为 \(n\) 的树,树边有边权.给你一个在 \(0 \sim n\)之内的正整数 \(k\) ,你要在这棵树中选择 \( ...
- 洛谷 P4201 设计路线 [NOI2008] 树形dp
正解:树形dp 解题报告: 大概是第一道NOI的题目?有点激动嘻嘻 然后先放个传送门 先大概港下这题的题意是啥qwq 大概就是给一棵树,然后可以选若干条链把链上的所有边的边权变成0,但是这些链不能有交 ...
- 洛谷P1040 加分二叉树(树形dp)
加分二叉树 时间限制: 1 Sec 内存限制: 125 MB提交: 11 解决: 7 题目描述 设一个n个节点的二叉树tree的中序遍历为(l,2,3,...,n),其中数字1,2,3,...,n ...
- 洛谷P4438 道路 [HNOI/AHOI2018] 树形dp
正解:树形dp 解题报告: 传送门! 昂首先看懂题目趴QwQ大概就是说有棵满二叉树,有n个叶子节点(乡村)和n-1个非叶子节点,然后这棵树的每个节点有三个属性abc,对每个非叶子节点可以从与子节点的两 ...
- 洛谷 P3267 [JLOI2016/SHOI2016]侦察守卫(树形dp)
题面 luogu 题解 树形\(dp\) \(f[x][y]表示x的y层以下的所有点都已经覆盖完,还需要覆盖上面的y层的最小代价.\) \(g[x][y]表示x子树中所有点都已经覆盖完,并且x还能向上 ...
- 洛谷P1351 联合权值(树形dp)
题意 题目链接 Sol 一道很简单的树形dp,然而被我写的这么长 分别记录下距离为\(1/2\)的点数,权值和,最大值.以及相邻儿子之间的贡献. 树形dp一波.. #include<bits/s ...
- 洛谷P4099 [HEOI2013]SAO(树形dp)
传送门 HEOI的题好珂怕啊(各种意义上) 然后考虑树形dp,以大于为例 设$f[i][j]$表示$i$这个节点在子树中排名第$j$位时的总方案数(因为实际只与相对大小有关,与实际数值无关) 我们考虑 ...
- 洛谷 P1351 联合权值 —— 树形DP
题目:https://www.luogu.org/problemnew/show/P1351 树形DP,别忘了子树之间的情况(拐一下距离为2). 代码如下: #include<iostream& ...
- 洛谷 P2634 聪聪可可 —— 树形DP / 点分治
题目:https://www.luogu.org/problemnew/show/P2634 今天刚学了点分治,做例题: 好不容易A了,结果发现自己写的是树形DP...(也不用找重心)(比点分治快) ...
- 洛谷P3047 [USACO12FEB]Nearby Cows(树形dp)
P3047 [USACO12FEB]附近的牛Nearby Cows 题目描述 Farmer John has noticed that his cows often move between near ...
随机推荐
- 分布式事务框架-fescar
https://github.com/alibaba/fescar/wiki/%E6%A6%82%E8%A7%88?spm=5176.11156381.0.0.b9f85ceegUXvCC
- 3 不用IDE开发groovy
1 不用IDE开发groovy 1.1 不用IDE开发的方法 可以在IDE中运行Groovy类或者脚本,但是Groovy也提供了其他运行途径.你能运行Groovy代码基于以下: · ...
- 2019.03.21 读书笔记 ==与Equals
首先得出一个结论:==是比较变量内存的数据,Equals是值比较.但是他们都能被重写,所以object又增加了一个RefrenceEquals不可被重写,只比较数据: [ReliabilityCont ...
- 2019.03.19 读书笔记 string与stringbuilder的性能
1 string与stringbuilder 并不是stringbuilder任何时候都在性能上占优势,在少量(大约个位数)的字符串时,并不比普通string操作快. string慢的原因不是stri ...
- C语言有GetOpenFile吗?
windows中有个GetOpenFile的函数,就是上面那个啦!!我们怎么来实现呢?要我用C语言写出来我真的跪了..但是我们可以输入文件的[绝对路径],配合fopen函数来实现的.. 注意问题 ①文 ...
- [转]How to Create Custom Filters in AngularJs
本文转自:http://www.codeproject.com/Tips/829025/How-to-Create-Custom-Filters-in-AngularJs Introduction F ...
- Murano Weekly Meeting 2015.10.13
Meeting time: 2015.October.13th 1:00~2:00 Chairperson: Serg Melikyan, PTL from Mirantis Meeting sum ...
- WSGI学习系列Paste
Paste has been under development for a while, and has lots of code in it. The code is largely decoup ...
- 【计算机网络】一步一步学习IP路由流程
TCP/IP协议簇是目前互联网应用最广的协议栈,谈到TCP/IP协议栈就不能不讲一讲IP路由的问题,因为在我们使用的网络通信中几乎每时每刻都在发生着IP路由的事件…….当你在网络世界中还是一位新手的时 ...
- telnet不能用,提示:-bash: telnet: command not found
1.[root@localhost ~]# telnet bash: telnet: command not found 2. 查询了是否安装Telnet包,结果如下: [root@localhos ...