POJ 3659 Cell Phone Network / HUST 1036 Cell Phone Network(最小支配集,树型动态规划,贪心)

Description

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 ≤ N; A ≠ B) there is a sequence of adjacent pastures such that A 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

Http

POJ:https://vjudge.net/problem/POJ-3659

HUST:https://vjudge.net/problem/HUST-1036

Source

最小支配集,树型动态规划,贪心

题目大意

在一棵树上选出最小的点集,使得每个点都满足自己在集合中或相连的点在集合中(一下简称某点被覆盖/被选)

解决思路

这道题的贪心解法在这里,那么本文就讲一讲DP的做法。

首先我们观察,一个点被覆盖只有三种情况

1.被它自己覆盖

2.被它的儿子节点覆盖

3.被它的父亲覆盖

根据以上的分析,我们就可以令F[u][0],F[u][1],F[u][2]分别表示u在上述的三种情况能得到的最小值。接下来就是推导出动归方程啦!

先来看简单点的两种情况F[u][0]和F[u][2](下面我们均用v来代表u的子节点)

F[u][0]代表的是u点选择u点进行覆盖,那么经过推到我们可得

\[F[u][0]=\Sigma(max\begin{cases}F[v][0]\\F[v][1]\\F[v][2]\end{cases})
\]

而F[u][2]则代表的是u被其父节点覆盖,这同样也代表着u不是被选中的点,也就是说u的子节点v的F[v][2]不放入考虑范围(为什么?因为F[v][2]代表的是v被父节点也就是u覆盖啦,但u又不选),那么我们就有

\[F[u][2]=\Sigma(max\begin{cases}F[v][0]\\F[v][1]\end{cases})
\]

最后就是F[u][1]啦。它代表的是u节点被其子节点覆盖。

稍微缓一下,这里说的覆盖可以>=1个子节点哦!

那么对于F[u][1]来说,它可以从v的哪些状态得到呢?

经过简单的思考,我们得出F[u][1]可以从F[v][1]和F[v][0]得到(为什么不能是F[v][2]呢?前面已经讲过了,既然选择F[u][1]计算,也就意味着u点不被选择去覆盖别的点)。那难道动归方程是这样的吗?

\[F[u][1]=\Sigma(max\begin{cases}F[v][0]\\F[v][1]\end{cases})
\]

且住,这样不就和F[u][2]一样了吗

不知道读者有没有发现问题,这样写出的方程在转移时可能出现问题,那就是有可能出现在求和时每一个v都取的是F[v][1],这也就意味着我们最后求出来的F[u][1]代表的解中u的子节点v都没有被选择去覆盖别的点!!!,而这与我们对F[u][1]的定义是矛盾的。

怎么办呢?我们要用一个bool类型的变量flag来记录下F[u][1]是否从F[v][0]这种状态转移过来过,如果没有,则要强制让一个从F[v][1]转移过来的变成从F[v][0]转移过来,并且还要保证尽量小

最后的问题是,如何强制呢?我们令一个变量inc=min(F[v][0]-F[v][1]),那么如果最后检查flag标记时若发现F[u][1]没有从F[v][0]转移来的历史记录,我们就F[u][1]+=inc就可以啦(这就相当于强制让一个从F[v][1]转移过来的变成从F[v][0]转移过来,并保证了最小)

所以最后F[u][1]的状态转移方程就是

\[F[u][1]=\begin{cases}\Sigma min(F[v][0],F[v][1]) \text (如果u的子节点v中有被选择的) \\\Sigma min(F[v][0],F[v][1])+inc \text (如果u的子节点v中没有被选择的)\end{cases}
\]

\[inc=min(F[v][0]-F[v][1])
\]

最后的最后要注意的地方就是最后输出答案的时候是min(F[1][0],F[1][1]),而不是min(F[1][0],F[1][1],F[1][2])(你问我为什么,1就是根节点,哪里会被其“父节点”覆盖呢)

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std; const int maxN=10001;
const int inf=147483647; int n;
vector<int> E[maxN];
int F[maxN][5]={0};
bool vis[maxN]; void dfs(int u); int main()
{
cin>>n;
for (int i=1;i<n;i++)
{
int x,y;
cin>>x>>y;
E[x].push_back(y);
E[y].push_back(x);
}
memset(vis,0,sizeof(vis));
dfs(1);
cout<<min(F[1][0],F[1][1])<<endl;
return 0;
} void dfs(int u)
{
F[u][0]=1;
F[u][2]=0;
F[u][1]=0;
vis[u]=1;
bool flag=0;//标记u的子树中计算F[u][1]时是否取过F[v][0]
int inc=inf;
for (int i=0;i<E[u].size();i++)
{
int v=E[u][i];
if (vis[v]==0)
{
dfs(v);
F[u][0]+=min(F[v][0],min(F[v][1],F[v][2]));
F[u][2]+=min(F[v][1],F[v][0]);
if (F[v][0]<=F[v][1])//这里就是对F[u][1]的处理啦,另外注意这里要取等
{
flag=1;
F[u][1]+=F[v][0];
}
else
{
inc=min(inc,(F[v][0]-F[v][1]));
F[u][1]+=F[v][1];
}
}
}
if (flag==0)//若在计算F[u][1]时没有从F[v][0]推导过来的,就要强制将一个转换成从F[v][0]推导过来。
{
F[u][1]+=inc;
}
return;
}

POJ 3659 Cell Phone Network / HUST 1036 Cell Phone Network(最小支配集,树型动态规划,贪心)-动态规划做法的更多相关文章

  1. POJ 3659 Cell Phone Network(树的最小支配集)(贪心)

    Cell Phone Network Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6781   Accepted: 242 ...

  2. poj-3659 Cell Phone Network(最小支配集+贪心)

    http://poj.org/problem?id=3659 Description Farmer John has decided to give each of his cows a cell p ...

  3. POJ 3398 Perfect Service(树型动态规划,最小支配集)

    POJ 3398 Perfect Service(树型动态规划,最小支配集) Description A network is composed of N computers connected by ...

  4. POJ 3398 Perfect Service --最小支配集

    题目链接:http://poj.org/problem?id=3398 这题可以用两种上述讲的两种算法解:http://www.cnblogs.com/whatbeg/p/3776612.html 第 ...

  5. POJ 2342 Anniversary party / HDU 1520 Anniversary party / URAL 1039 Anniversary party(树型动态规划)

    POJ 2342 Anniversary party / HDU 1520 Anniversary party / URAL 1039 Anniversary party(树型动态规划) Descri ...

  6. 树的最小支配集 E - Cell Phone Network POJ - 3659 E. Tree with Small Distances

    E - Cell Phone Network POJ - 3659 题目大意: 给你一棵树,放置灯塔,每一个节点可以覆盖的范围是这个节点的所有子节点和他的父亲节点,问要使得所有的节点被覆盖的最少灯塔数 ...

  7. POJ 3659 Cell Phone Network 最小支配集模板题(树形dp)

    题意:有以个 有 N 个节点的树形地图,问在这些顶点上最少建多少个电话杆,可以使得所有顶点被覆盖到,一个节点如果建立了电话杆,那么和它直接相连的顶点也会被覆盖到. 分析:用最少的点覆盖所有的点,即为求 ...

  8. POJ3659 Cell Phone Network(树上最小支配集:树型DP)

    题目求一棵树的最小支配数. 支配集,即把图的点分成两个集合,所有非支配集内的点都和支配集内的某一点相邻. 听说即使是二分图,最小支配集的求解也是还没多项式算法的.而树上求最小支配集树型DP就OK了. ...

  9. POJ 2152 fire / SCU 2977 fire(树型动态规划)

    POJ 2152 fire / SCU 2977 fire(树型动态规划) Description Country Z has N cities, which are numbered from 1 ...

随机推荐

  1. 使用CSS设置滚动条样式以及如何去掉滚动条的方法

    <STYLE> BODY { SCROLLBAR-FACE-COLOR: #f892cc; SCROLLBAR-HIGHLIGHT-COLOR: #f256c6; SCROLLBAR-SH ...

  2. [c++]大数运算1---利用C++ string实现任意长度正小数、整数之间的加减法

    一.概述 本文属于大大维原创,未经笔者本人允许,严禁转载!!! C/C++中的int类型能表示的范围是-2E31-2E31–1.unsigned类型能表示的范围是0-2E32–1,即 0-429496 ...

  3. ES6解构赋值详解

    文章转载自:http://www.zhufengpeixun.cn/article/167 解构赋值(destructuring assignment)语法是一个 Javascript 表达式,这种语 ...

  4. [Leetcode] Binary tree level order traversal二叉树层次遍历

    Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, ...

  5. 在WIN SERVER 2016上安装DOCKER(带过坑)

    目录 1    概要    1 1.1    主要优势    1 2    在Windows Server上部署Docker    2 概要 博客使用Word发博,发布后,排版会出现很多问题,敬请谅解 ...

  6. vue 高德地图之玩转周边

    前言:在之前的博客中,有成功引入高德地图,这是以前的地址  vue 调用高德地图. 因为一些需求,需要使用到地图的周边功能. 完整的项目代码请查看  我的github 一 .先看要实现的结果,参考了链 ...

  7. VirtualBox的快照功能

    VirtualBox是非常好用的一个虚拟机软件,无论是性能还是易用性不比商用的Vmware差.VirtualBox最初是Sun公司的产品,由于Sun被Oracle收购,现在也归Oracle了.除了虚拟 ...

  8. Ubuntu发行版升级

    从UK 13.10升级到UK 14.10 方法一: 1.sudo apt-get update   2.sudo update-manager -c -d   3.选择upgrade(升级)  方法二 ...

  9. java入门学习笔记之2(Java中的字符串操作)

    因为对Python很熟悉,看着Java的各种字符串操作就不自觉的代入Python的实现方法上,于是就将Java实现方式与Python实现方式都写下来了. 先说一下总结,Java的字符串类String本 ...

  10. JS 冒泡排序从学到优化

    目的:理解算法 深化算法 冒泡排序: 直接上动图好于文字 一个冒泡实例 45,67,23,88,21,6,99// 第一轮 6次// 45 67 23 88 21 6 99// 45 23 67 88 ...