点此看题面

大致题意: 在一棵树中有\(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)的更多相关文章

  1. [51nod1299]监狱逃离

    到现在还是不会写系列,直接贴题解了. http://www.51nod.com/question/index.html#!questionId=1157 #include<cstdio> ...

  2. 动态规划专题(二)——树形DP

    前言 \(DP\)这东西真的是博大精深啊...... 简介 树形\(DP\),顾名思义,就是在树上操作的\(DP\),一般可以用\(f_i\)表示以编号为\(i\)的节点为根的子树中的最优解. 转移的 ...

  3. poj3417 LCA + 树形dp

    Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4478   Accepted: 1292 Descripti ...

  4. COGS 2532. [HZOI 2016]树之美 树形dp

    可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...

  5. 【BZOJ-4726】Sabota? 树形DP

    4726: [POI2017]Sabota? Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 128  Solved ...

  6. 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)

    题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...

  7. 树形DP

    切题ing!!!!! HDU  2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...

  8. BZOJ 2286 消耗战 (虚树+树形DP)

    给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...

  9. POJ2342 树形dp

    原题:http://poj.org/problem?id=2342 树形dp入门题. 我们让dp[i][0]表示第i个人不去,dp[i][1]表示第i个人去 ,根据题意我们可以很容易的得到如下递推公式 ...

随机推荐

  1. webpack -- 多页面简单小例

    有时单页面并不能满足我们的业务需求,就需要去构建多页面应用,以下为简单小例: entry:{ index:'./src/module/index/index.js', student:'./src/m ...

  2. Educational Codeforces Round 57D(DP,思维)

    #include<bits/stdc++.h>using namespace std;char s[100007];long long a[100007];long long dp[100 ...

  3. 置换群(本蒟蒻瞎BB的)(未完)

    置换群(本蒟蒻瞎BB的)(未完) 群的定义 给定一个集合\(G=\{a, b, c...\}\)和集合\(G\)上的二元运算*,并满足: 封闭性:\(\forall a, b \in G, \exis ...

  4. Java学习笔记——Map接口

    Map接口 Map接口 Map接口中键和值一一映射. 可以通过键来获取值. 异常 NoSuchElementException:访问的值不存在 ClassCastException:对象类型错误 Un ...

  5. 如何阻止<a>标签的页面跳转

    当页面中a标签不需要执行任何页面跳转行为时: 1.标签属性href,使其指向空或不返回任何内容 <a href="javascript:void(0);" >页面不跳转 ...

  6. centos 基础设置

    centos 6 关闭防火墙 查看防火墙是否开启 service iptables status 停止防火墙 service iptables stop 禁止开机自启动防火墙 chkconfig ip ...

  7. EIGRP-2-EIGRP的度量

    EIGRP使用多种类型的度量值来描述一条路由的不同技术属性,称为组合度量或度量组合.这些组合度量参数包括带宽.延迟.可靠性.负载.MTU和跳数.这6个参数中的前4个通过一个著名的公式组合在一起,计算出 ...

  8. POJ1043 What's In A Name?

    题目来源:http://poj.org/problem?id=1043 题目大意: 一个犯罪团伙有n个成员,每人有一个唯一的字符串作为id,每人还有一个唯一的字符串作为name.该团伙有一个hideo ...

  9. Javascript专题(三)b.各种轮播和细节分析--上下滚动轮播

    这一次,我们用原生JS实现上下滚动方式的轮播.顺带学习一下用JS来创建HTML元素. 上一次写的轮播是淡入淡出效果的,相对来说其实是比较简单的. github源码: 上下轮播源码-github A. ...

  10. Qt学习之网络编程(一)

    一些说明 学了有一段时间的python了,小项目做了不少,最近由于项目需要,所以要回归老本行了,开始重点突击C++和qt.python的网络爬虫系列有时间就更吧. 获取本机网络信息 在网络应用中,经常 ...