【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个人去 ,根据题意我们可以很容易的得到如下递推公式 ...
随机推荐
- 飘逸的python - @staticmethod和@classmethod的作用与区别
一般来说,要使用某个类的方法,需要先实例化一个对象再调用方法. 而使用@staticmethod或@classmethod,就可以不需要实例化,直接类名.方法名()来调用. 这有利于组织代码,把某些应 ...
- cf822D(质因子)
题目链接: http://codeforces.com/problemset/problem/822/D 题意: 输入 t, l, r 求 t0·f(l) + t1·f(l + 1) + ... + ...
- [Xcode 实际操作]四、常用控件-(17)为MKMapView地图上显示提示框
目录:[Swift]Xcode实际操作 本文将演示当点击地图上的标注圆点时,弹出信息窗口. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] import UIKit ...
- Google Guetzli是如何压缩图片的?
你可能已经知道,现在网页文件的平均大小比Doom游戏的安装文件还还大. 文件变大的原因之一是图片的增加,并且还需要支持更高的分辨率. Google来拯救了 Google刚刚发布了一种新的JPEG压缩算 ...
- css 权重值(层叠性)详解
目录 css权重值(重叠性)实例 权重值的计算 !important 提升权重值实例 什么情况下可以使用!important ? 总结: css权重值(重叠性)实例 css中有很多选择器,那在多个选择 ...
- Angular输入框内按下回车会触发其它button的点击事件的解决方法
方法:给button按钮添加type=“botton”属性
- iOS开发 - CocoaPods远程私有库从0到1
1. 创建主工程 路径:/Users/Funky/Desktop/CocoaPodRemoteLib/MyMainProject/MyMainProject.xcodeproj 2. 在码云(htt ...
- 练习十八:求这样的一组数据和,s=a+aa+aaa+aaaa+aa...a,其中a为一个数字
例如:2+22+222+2222+22222(此时共有5个数字相加),这里具体几个数字由键盘控制 方法一:普通做法 a = int(input("计算要加的数(1-9之间数):") ...
- jsonp——使用公共接口获取数据
demo: <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8 ...
- 019 Remove Nth Node From End of List 删除链表的倒数第N个节点
给定一个链表,删除链表的倒数第 n 个节点并返回头结点.例如,给定一个链表: 1->2->3->4->5, 并且 n = 2.当删除了倒数第二个节点后链表变成了 1->2 ...