题干:

Farmer John has decided to give each of his cows a cell phone in hopes to encourage their social interaction. This, however, requires him to set up cell phone towers on his N (1 ≤ N ≤ 10,000) pastures (conveniently numbered 1..N) so they can all communicate.

Exactly N-1 pairs of pastures are adjacent, and for any two pastures A and B (1 ≤ A≤ N; 1 ≤ B ≤ NA ≠ B) there is a sequence of adjacent pastures such that is the first pasture in the sequence and B is the last. Farmer John can only place cell phone towers in the pastures, and each tower has enough range to provide service to the pasture it is on and all pastures adjacent to the pasture with the cell tower.

Help him determine the minimum number of towers he must install to provide cell phone service to each pasture.

Input

* Line 1: A single integer: N
* Lines 2..N: Each line specifies a pair of adjacent pastures with two space-separated integers: A and B

Output

* Line 1: A single integer indicating the minimum number of towers to install

Sample Input

5
1 3
5 2
4 3
3 5

Sample Output

2

解题报告:

由于这是在树上求最值的问题,显然可以用树形动态规划,只是状态的设计比较复杂。为了保证动态规划的正确性,对于每个点设计了三种状态,这三种状态的意义如下:

①dp[i][2]:表示点i属于支配集,并且以点i为根的子树都被覆盖了的情况下支配集中所包含的的最少点的个数。

②dp[i][1]:i不属于支配集,且以i为根的子树都被覆盖,且i被其中不少于1个子节点覆盖的情况下支配集中所包含最少点的个数。

③dp[i][0]:i不属于支配集,且以i为根的子树都被覆盖,且i没被子节点覆盖的情况下支配集中所包含最少点的个数。

对于第一种状态,dp[i][0]等于每个儿子节点的3种状态(其儿子是否被覆盖没有关系)的最小值之和加1,即只要每个以i的儿子为根的子树都被覆盖,再加上当前点i,所需要的最少点的个数,方程如下:

dp[i][2]=1+Σmin(dp[u][2],dp[u][1],dp[u][0])(p[u]=i).

对于第二种状态,如果点i没有子节点,那么dp[i][1]=INF;否则,需要保证它的每个以i的儿子为根的子树都被覆盖,那么要取每个儿子节点的前两种状态的最小值之和,因为此时i点不属于支配集,不能支配其子节点,所以子节点必须已经被支配,与子节点的第三种状态无关。如果当前所选的状态中,每个儿子都没有被选择进入支配集,即在每个儿子的前两种状态中,第一种状态都不是所需点最少的,那么为了满足第二种状态的定义,需要重新选择点i的一个儿子的状态为第一种状态,这时取花费最少的一个点,即取min(dp[u][2]-dp[u][1])的儿子节点u,强制取其第一种状态,其他儿子节点都取第二种状态,转移方程为:

if(i没有子节点)dp[i][1]=INF

else dp[i][1]=Σmin(dp[u][2],dp[u][1])+inc

其中对于inc有:

if(上面式子中的Σmin(dp[u][2],dp[u][1])中包含某个dp[u][2])inc=0;

else inc=min(dp[u][2]-dp[u][1])。

对于第三种状态,i不属于支配集,且以i为根的子树都被覆盖,又i没被子节点覆盖,那么说明点i和点i的儿子节点都不属于支配集,则点i的第三种状态只与其儿子的第二种状态有关,方程为

dp[i][0]=Σdp[u][1]

AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
const int MAX = 2e5 + 5;
const int INF = 0x3f3f3f3f;
int head[MAX];
struct Edge {int to,ne;
} e[MAX];
int tot;
void add(int u,int v) {e[++tot].to =v;e[tot].ne = head[u];head[u] = tot;
}
int Min(int a,int b,int c) {if(a < b) return min(a,c);else return min(b,c);
}
int Min(int a,int b) {return min(a,b);
}
int dp[MAX][3];//0不选并且没有被覆盖掉,1不选但是被覆盖到了,2选 ,(同时要保证子节点全部被覆盖到了)
void dfs(int cur,int rt) {dp[cur][2] = 1;int flag = 1,tmp=INF;for(int i = head[cur]; i!=-1; i=e[i].ne) {int v = e[i].to;if(v == rt) continue;dfs(v,cur);dp[cur][2] += Min(dp[v][0],dp[v][1],dp[v][2]);dp[cur][0] += Min(dp[v][2],dp[v][1]); //不能由下一层没被覆盖到转移!!if(dp[v][2]<=dp[v][1]) {dp[cur][1]+=dp[v][2];flag=0;} else {dp[cur][1]+=dp[v][1];tmp=min(tmp,dp[v][2]-dp[v][1]);}}if(flag)    //还没有选儿子,加上这个差值,补回一个儿子dp[cur][1]+=tmp;
}
int main() {int n;cin>>n;memset(head,-1,sizeof head);for(int a,b,i = 1; i<=n-1; i++) {scanf("%d%d",&a,&b);add(a,b);add(b,a);}dfs(1,-1);printf("%d\n",Min(dp[1][1],dp[1][2]));return 0 ;
}

但是不是很理解为什么  dp[cur][0] +=dp[v][1];  就WA?

他这样写:

按照这个定义:

①dp[i][0]:表示点i属于支配集,并且以点i为根的子树都被覆盖了的情况下支配集中所包含的的最少点的个数。

②dp[i][1]:i不属于支配集,且以i为根的子树都被覆盖,且i被其中不少于1个子节点覆盖的情况下支配集中所包含最少点的个数。

③dp[i][2]:i不属于支配集,且以i为根的子树都被覆盖,且i没被子节点覆盖的情况下支配集中所包含最少点的个数。

void DP(int u,int p) {dp[u][2]=0;dp[u][0]=1;bool s=false;int sum=0,inc=INF;int k;for(k=head[u]; k!=-1; k=edge[k].next) {int to=edge[k].to;if(to==p)continue;DP(to,u);dp[u][0]+=min(dp[to][0],min(dp[u][1],dp[u][2]));if(dp[to][0]<=dp[to][1]) {sum+=dp[to][0];s=true;} else {sum+=dp[to][1];inc=min(inc,dp[to][0]-dp[to][1]);}if(dp[to][1]!=INF&&dp[u][2]!=INF)dp[u][2]+=dp[to][1];else dp[u][2]=INF;}if(inc==INF&&!s)dp[u][1]=INF;else {dp[u][1]=sum;if(!s)dp[u][1]+=inc;}
}

也是对的,,,这样就可以   dp[cur][2] 只跟 dp[v][1];有关????why???


另一个题解:

#include<stdio.h>
#include<string.h>
#define clr(x)memset(x,0,sizeof(x))
int min(int a,int b)
{ return a<b?a:b; }
#define maxn 100005
#define INF 0x1f1f1f1f
struct node
{int to;int next;
}e[1000000];
int tot;
int head[maxn];
int dp[maxn][3];
void add(int s,int u)
{e[tot].to=u;e[tot].next=head[s];head[s]=tot++;
}
// dp[r][0] = min(dp[i][0],dp[i][1],dp[i][2])自身建
// dp[r][1] = min(dp[i][0],dp[i][1]) 子节点建
// dp[r][2] = min(dp[i][0],dp[i][1]) 父节点建
int n;
int v[maxn];
void dfs(int r)
{v[r]=1;int i,k;int flag=1,ff=1,mi=INF,t;dp[r][0]=1;for(i=head[r];i;i=e[i].next){k=e[i].to;if(!v[k]){flag=0;dfs(k);dp[r][0]+=min(dp[k][0],min(dp[k][1],dp[k][2]));if(dp[k][1]>=dp[k][0]){ff=0;dp[r][1]+=dp[k][0];}else {dp[r][1]+=dp[k][1];if(dp[k][0]<mi){mi=dp[k][0];t=dp[k][1];}}dp[r][2]+=min(dp[k][0],dp[k][1]);}}if(ff)dp[r][1]+=mi-t;if(flag){dp[r][0]=1;dp[r][1]=INF;dp[r][2]=0;}
}
int main()
{int a,b,i;while(scanf("%d",&n)!=EOF){tot=1;clr(v);clr(dp);clr(head);for(i=1;i<n;i++){scanf("%d%d",&a,&b);add(a,b);add(b,a);}if(n==1){printf("1\n");continue;}dfs(1);printf("%d\n",min(dp[1][0],dp[1][1]));}return 0;
}

*【POJ - 3659】Cell Phone Network (树形dp,最小支配集)相关推荐

  1. USACO 2008 Jan Gold 3.Cell Phone Network 树形dp

    本题的大意就是在一棵树上选一些节点,被选中的节点可以覆盖他相 邻的点,问最少需要放几个节点\text{本题的大意就是在一棵树上选一些节点,被选中的节点可以覆盖他相 邻的点,问最少需要放几个节}\\\t ...

  2. 牛客假日团队赛8:H.Cell Phone Network(最小支配集)

    链接:https://ac.nowcoder.com/acm/contest/1069/A 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言6553 ...

  3. 1579: 【例 5】皇宫看守(最小支配集——贪心求解/树形DP)

    [题目描述] 太平王世子事件后,陆小凤成了皇上特聘的御前一品侍卫. 皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状,某些宫殿间可以互相望见.大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全 ...

  4. 树形DP求树的最小支配集,最小点覆盖,最大独立集

    转自:https://www.cnblogs.com/Ash-ly/p/5783877.html 一:最小支配集 考虑最小支配集,每个点有两种状态,即属于支配集合或者不属于支配集合,其中不属于支配集合 ...

  5. 最小支配集,最小点覆盖,最大独立集(贪心/DP)

    最小支配集(minimal dominating set):对于图G=(V,E)来说,设V'是图G的一个支配集,则对于图中的任意一个顶点u,要么属于集合V',要么与V'中的顶点相连. 在V'中除去任何 ...

  6. [UVA-1218] Perfect Service(树的最小支配集)

    题目链接:https://vjudge.net/problem/UVA-1218 题目大意:给你一棵无向树,让你求树的最小支配集,但是有一个要求是除最小支配集外剩下的任何一个结点不能同时连接支配集中的 ...

  7. 树的最小支配集、最小点覆盖、最大独立集【模板】

    最小支配集:指从所有顶点中取尽量少的点组成一个集合,使得剩下的所有点都与取出来的点有边相连.顶点个数最小的支配集被称为最小支配集.这里用贪心法来求. 1.以1号点深度优先搜索整棵树,求出每个点在DFS ...

  8. 贪心法求树的最小支配集,最小点覆盖,最大独立集

    原文地址(转自 Ashly的博客) 定义: 最小支配集:对于图G = (V, E) 来说,最小支配集指的是从 V 中取尽量少的点组成一个集合, 使得 V 中剩余的点都与取出来的点有边相连.也就是说,设 ...

  9. POJ 1155 TELE【树形DP】

    POJ 1155 TELE http://poj.org/problem?id=1155 大意:某电台要广播一场比赛,该电台网络是由N个网点组成的一棵树,其中M个点为客户端, 其余点为转发站.客户端i ...

最新文章

  1. jquery中ajax的dataType属性包括哪几项
  2. robotframework - 运行报错提示 No keyword with name 'Open Browser' found.
  3. AndroidUI 视图动画-旋转动画效果 (RotateAnimation)
  4. hql中获取前一天的数据_oracle实现动态查询前一天早八点到当天早八点的数据功能示例...
  5. ITK:使用FFT与输入图像的掩码图像进行归一化相关
  6. 使用python学线性代数_最简单的神经网络简介| 使用Python的线性代数
  7. Android 换肤demo,轻量快捷接入集成,判断是否夜间模式
  8. 从留存的本质出发,制定留存策略
  9. maven 学习---Maven本地资源库
  10. poj 3181 Dollar Dayz (整数划分问题---递归+DP)
  11. Tomcat配置Basic认证方案(一)
  12. thymeleaf学习笔记
  13. java转换ppt,ppt转成图片 乱码问题解决
  14. 冒泡排序(Java)
  15. 简单几步去掉百度热搜
  16. java mysql连接池配置_Java数据库连接池的几种配置方法(以MySQL数据库为例)
  17. 江苏辖区农商银行2020年(科技类)
  18. session error的问题
  19. 常用计算机制图软件,常用的电脑画图软件有什么?
  20. 电脑故障一查通 软件教学

热门文章

  1. [Leedcode][JAVA][第33题][搜索旋转排序数组]
  2. [Leedcode][JAVA][第11题][盛最多水的容器][双指针][贪心]
  3. php为什么搜不到字段,php-通过多个字段搜索.有时一个领域,有时不止一个领域
  4. mysql命令_MySQL常用操作命令
  5. centos 源码安装mysql5.6_CentOS 7下源码安装MySQL 5.6
  6. mysql 自动备份删除_mysql自动备份删除5天前的备份
  7. python中setup什么意思_一个关于python3中setup.py小概念
  8. dts数据库迁移工具_传统数据库迁移上云利器-ADAM
  9. GenerateProjectFiles.bat分析
  10. reactor设计模式 1