【51nod1299】监狱逃离(树形DP)
大致题意: 在一棵树中有\(N\)条边连接\(N+1\)个节点,现在已知这棵树上的\(M\)个节点,要求封住最少的节点,使这\(M\)个节点中的任意一个节点无法到达叶子节点,若能办到输出最少封住的节点数,若不能输出\(-1\)。
树形DP
这道题目的正解是树形\(DP\)(\(hl666\)大佬说用\(O(n^2m)\)的最小割也可以过这道题,不过这篇博客并不讨论这种做法,他能做出来是因为他是常数之神)。
树形\(DP\),一般都将状态由子节点向父节点转移,这题当然也不例外。
我们可以用\(f\)数组来存储每一个节点的状态:
若\(f[i]=0\),则说明该节点已被完全封死,相当于既不可能有犯人到达这里,也不可能从这里到达出口。
若\(f[i]=1\),则说明可以从这个节点到达叶子节点。
若\(f[i]=2\),则说明有犯人可以到达该节点。
每一次转移,我们可以用一个s[]数组来统计当前节点的子节点中\(f[son[i]]\)分别为\(0,1,2\)的次数,并依次进行分类讨论:
若当前节点有犯人,则需要在该节点的子节点中的每个可以到达叶子节点的节点上安排一个警卫。且\(f[x]=2\)(当前节点上有犯人,所以犯人可以到达该节点)。
若既有犯人可以到达该节点的某个子节点,又可以通过该节点的某个子节点到达叶子节点,这说明有犯人可以通过该节点逃出监狱,则需在这个节点安排一个警卫。且\(f[x]=0\)(当前节点安排了警卫,所以被完全封死)。
否则,如果该节点的某个子节点可以到达叶子节点,则说明该节点也可以到达叶子节点,因此\(f[x]=1\)。
否则,如果有犯人可以到达该节点的某个子节点,则说明犯人也可以到达该节点,因此\(f[x]=2\)。
如果以上情况皆不满足,这说明该节点是叶节点或其子节点全被封死,则特判其为叶子节点的情况,若其不是叶子节点则\(f[x]=0\)。
既然这样,就很容易进行动态规划了,具体代码如下:
代码
#include<bits/stdc++.h>
#define N 100000
using namespace std;
int n,m,ee=0,ans,a[N+5]={0},lnk[N+5]={0},OUT[N+5]={0},f[N+5]={0};
struct edge
{
int to,nxt;
}e[2*N+5];
inline char tc()
{
static char ff[100000],*A=ff,*B=ff;
return A==B&&(B=(A=ff)+fread(ff,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
x=0;int f=1;char ch;
while(!isdigit(ch=tc())) if(ch=='-') f=-1;
while(x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc()));
x*=f;
}
inline void write(int x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
inline void add(int x,int y)
{
e[++ee]=(edge){y,lnk[x]},lnk[x]=ee,++OUT[x];
}
inline void dp(int x,int lst)//具体的DP过程
{
int s[3];s[0]=s[1]=s[2]=0;//用s[]数组来统计当前节点子节点中各种状态的次数
register int i;
for(i=lnk[x];i;i=e[i].nxt)
if(e[i].to^lst) dp(e[i].to,x),++s[f[e[i].to]];//先将其子节点进行DP,是一个递归的过程
//接下来是分类讨论的过程
if(a[x]) ans+=s[1],f[x]=2;//若当前节点有犯人
else if(s[1]&&s[2]) ans++,f[x]=0;//若当前节点既能到达,又能出去
else if(s[1]) f[x]=1;//若当前节点能出去
else if(s[2]) f[x]=2;//若当前节点能到达
else if(s[0]) f[x]=0;//若以上情况皆不满足且该节点不是叶节点
}
int main()
{
register int i;int x,y,fst=-1;
for(read(n),read(m),i=1;i<=n;++i)
read(x),read(y),add(x,y),add(y,x);
for(i=1;i<=m;++i)
{
read(x),a[x]=1;
if(OUT[x]==1) return puts("-1"),0;//若有叶子节点关押犯人,则该犯人能直接逃脱
}
for(i=1;i<=n;++i)
if(!(OUT[i]^1)) (fst==-1?fst=i:0),f[i]=1;//将叶子节点的状态初始化为1
dp(fst,0);//从一个叶子节点开始DP
return write(f[fst]==2?ans+1:ans),0;//特判该节点为2,即犯人可以到达的情况,由于当前节点是叶子节点,所以要在当前节点在安排一个警卫,答案加1
}
【51nod1299】监狱逃离(树形DP)的更多相关文章
- [51nod1299]监狱逃离
到现在还是不会写系列,直接贴题解了. http://www.51nod.com/question/index.html#!questionId=1157 #include<cstdio> ...
- 动态规划专题(二)——树形DP
前言 \(DP\)这东西真的是博大精深啊...... 简介 树形\(DP\),顾名思义,就是在树上操作的\(DP\),一般可以用\(f_i\)表示以编号为\(i\)的节点为根的子树中的最优解. 转移的 ...
- poj3417 LCA + 树形dp
Network Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 4478 Accepted: 1292 Descripti ...
- COGS 2532. [HZOI 2016]树之美 树形dp
可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...
- 【BZOJ-4726】Sabota? 树形DP
4726: [POI2017]Sabota? Time Limit: 20 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 128 Solved ...
- 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)
题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...
- 树形DP
切题ing!!!!! HDU 2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...
- BZOJ 2286 消耗战 (虚树+树形DP)
给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...
- POJ2342 树形dp
原题:http://poj.org/problem?id=2342 树形dp入门题. 我们让dp[i][0]表示第i个人不去,dp[i][1]表示第i个人去 ,根据题意我们可以很容易的得到如下递推公式 ...
随机推荐
- 浅析HTTP协议get请求与post请求
一.HTTP简介 1. HTTP协议:(hypertext transport protocol),即超文本传输协议.这个协议详细规定了浏览器和万维网服务器之间互相通信的规则(报文格式). 2.报文: ...
- ios一个自定义的下拉多选菜单
前段时间项目刚好要做到条件筛选菜单,正好找到一些别人写的,结合自己实际需求进行优化修改,一个实用的多条件筛选菜单,根据其他的下拉进行一些改进. 点击后返回点击文字显示 github地址:https:/ ...
- bzoj5506:[gzoi2019]旅行者
传送门 正反两边dijkstra染色,然后枚举一下边,求出最小值就好啦 代码: #include<cstdio> #include<iostream> #include< ...
- 洛谷 P2024 [NOI2001]食物链 (并查集)
嗯... 题目链接:https://www.luogu.org/problemnew/show/P2024 这道题和团伙这道题的思想比较类似,都是一个数组分成几个集合,但这道题的思路更加混乱,建议没做 ...
- Java基础笔记(十六)——继承
继承 提取出一些共性特征,作为父类,子类就可以继承父类的这些开放成员,子类再添加自己独有的属性和方法.如果再有类具有这些共同特征,也可继承这个父类. 特点:1.利于代码复用 2.缩短开发周期 ...
- excel单元格内容合并
这几天在整理数据,有时候数据都在表格的不同单元格中,想把两格内容合并为一格,于是验证了两种方法 方法一: (1)在B1输入公式=A1&B1 (2)做完第一步后,选中B1后,鼠标移到单元格右下出 ...
- JavaScript事件模型及事件代理
事件模型 JavaScript事件使得网页具备互动和交互性,我们应该对其深入了解以便开发工作,在各式各样的浏览器中,JavaScript事件模型主要分为3种:原始事件模型.DOM2事件模型.IE事件模 ...
- IDEA右键新建时没有Java Class选项
今天在IDEA中新建了一个maven工程,但是在我想要新建Class时发件右键菜单里竟然没有Java Class选项!如下图所示: 如上图红圈所示,我们可以根据对项目的任意目录进行这五种目录类型标注, ...
- js 数据类型及检测
js中基本数据类型有6种number.string.undefined.null.boolean,Symbol (ES6 新增,表示独一无二的值),还有一种数据类型为引用数据类型统称为Object对象 ...
- 【C#】=>符号的使用
Lambda表达式.Lambda表达式是C#3.0的新内容,如果您之前学习的C#2.0,不认识也就不奇怪了.给您举个例子.例如,我定义一个委托:delegate int Method(int a, i ...