点此看题面

大致题意: 在一棵树中有\(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. Mac安装vue

     Mac安装vue 一.安装brew 打开终端运行以下命令: /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com ...

  2. Objective-C的Runtime System

    [0] Outline --  [1] 版本和平台 --  [2] 与Runtime System交互 --  [3] 方法的动态决议 --  [4] 消息转发 --  [5] 类型编码 --  [6 ...

  3. Nacos深入浅出(十)

    基本上到第9篇,整个请求的一套就结束了,感觉这里跳跳绕绕很多东西,下面我们来做个总结:从Nacos配置平台修改,到Client请求更新,事件触发去取值返回给客户端,整个过程感觉只分析到了4.5层的深度 ...

  4. EOS 数据签名与公匙验证代码用例

    本文编写了一个小例子诠释了EOS是如何对数据签名与校验的,通过本文可以理解了签名的重要性和数据的不可篡改性. 系统: ubuntu  版本为EOS1.1.1 注:因为本文的程序是把EOS里面的钱包和f ...

  5. [USACO09FEB]庙会班车Fair Shuttle 线段树维护maxx&&贪心

    题目描述 Although Farmer John has no problems walking around the fair to collect prizes or see the shows ...

  6. SCOJ4427 / TOPOI 4404: Miss Zhao's Graph 解题报告

    题目链接 SCOJ TOPOI 题目描述 Problem 给定一个包含n个顶点m条边的带权有向图,找一条边数最多的路径,且路径上的边的权值严格递增.图中可能有重边和自环. Input Data 第一行 ...

  7. CCF201612-1 中间数(二分思想)

    问题链接:CCF201612试题. .对n个数进行排序,找出中间那个数,然后将中间那个数的左右与其相等的数去掉,看左右剩下的数个数是否相等,如果相等则中间那个数就是答案,否在输出-1. 问题描述 问题 ...

  8. Codeforces Round #364 (Div. 2) C

    Description Sergei B., the young coach of Pokemons, has found the big house which consists of n flat ...

  9. java——集合、泛型、ArrayList、LinkedList、foreach循环、模拟ktv点歌系统

    集合:一系列特殊的类,这些类可以存储任意类型的对象,长度可变,集合类都在java.util包中. 但是集合记不住对象的类型,当把对象从集合中取出时这个对象的编译类型就变成了Object类型.这样在取元 ...

  10. Java中的Enum(枚举)用法介绍

    1. 关于Java Enum:学过C/C++等语言的人,应该都对Enum类型略知一二.Enum一般用来表示一组相同类型的常量.如性别.日期.月份.颜色等.对这些属性用常量的好处是显而易见的,不仅可以保 ...