POJ 3659 Cell Phone Network / HUST 1036 Cell Phone Network(最小支配集,树型动态规划,贪心)-动态规划做法
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][2]则代表的是u被其父节点覆盖,这同样也代表着u不是被选中的点,也就是说u的子节点v的F[v][2]不放入考虑范围(为什么?因为F[v][2]代表的是v被父节点也就是u覆盖啦,但u又不选),那么我们就有
\]
最后就是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][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]的状态转移方程就是
\]
\]
最后的最后要注意的地方就是最后输出答案的时候是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(最小支配集,树型动态规划,贪心)-动态规划做法的更多相关文章
- POJ 3659 Cell Phone Network(树的最小支配集)(贪心)
Cell Phone Network Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6781 Accepted: 242 ...
- 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 ...
- POJ 3398 Perfect Service(树型动态规划,最小支配集)
POJ 3398 Perfect Service(树型动态规划,最小支配集) Description A network is composed of N computers connected by ...
- POJ 3398 Perfect Service --最小支配集
题目链接:http://poj.org/problem?id=3398 这题可以用两种上述讲的两种算法解:http://www.cnblogs.com/whatbeg/p/3776612.html 第 ...
- 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 ...
- 树的最小支配集 E - Cell Phone Network POJ - 3659 E. Tree with Small Distances
E - Cell Phone Network POJ - 3659 题目大意: 给你一棵树,放置灯塔,每一个节点可以覆盖的范围是这个节点的所有子节点和他的父亲节点,问要使得所有的节点被覆盖的最少灯塔数 ...
- POJ 3659 Cell Phone Network 最小支配集模板题(树形dp)
题意:有以个 有 N 个节点的树形地图,问在这些顶点上最少建多少个电话杆,可以使得所有顶点被覆盖到,一个节点如果建立了电话杆,那么和它直接相连的顶点也会被覆盖到. 分析:用最少的点覆盖所有的点,即为求 ...
- POJ3659 Cell Phone Network(树上最小支配集:树型DP)
题目求一棵树的最小支配数. 支配集,即把图的点分成两个集合,所有非支配集内的点都和支配集内的某一点相邻. 听说即使是二分图,最小支配集的求解也是还没多项式算法的.而树上求最小支配集树型DP就OK了. ...
- POJ 2152 fire / SCU 2977 fire(树型动态规划)
POJ 2152 fire / SCU 2977 fire(树型动态规划) Description Country Z has N cities, which are numbered from 1 ...
随机推荐
- 矢量量化(VQ)
作者:桂. 时间:2017-05-31 21:14:56 链接:http://www.cnblogs.com/xingshansi/p/6925955.html 前言 VQ(Vector Quant ...
- python 字符串常用方法
字符串常用方法 capitalize() String.capitalize() 将字符串首字母变为大写 name = 'xiaoming' new_name = name.capitalize() ...
- SQL Server中对存储过程的理解
数据库的存储过程理解为,处理数据的子程序,写起来像函数,用起来像函数,在SQL Server中存储过程分为两大类,系统的和自定义的,系统的都放在master系统数据库中,自定义就是自己去写的,用DDL ...
- MD5加密算法(信息摘要算法)、Base64算法
1 什么是MD5 信息摘要算法,可以将字符进行加密,每个加密对象在进行加密后都是等长的 应用场景:将用户密码经过MD5加密后再存储到数据库中,这样即使是超级管理员也没有能力知道用户的具体密码是多少:因 ...
- javaSE_05Java中方法(函数)与重载、递归
1.方法的声明和调用 什么是方法?为什么需要方法?代码复用,方便软件升级 什么是方法? 具备特定功能的一段独立的代码段 标准的方法格式:(注意格式的顺序) 修饰符 返回值类型 方法名(参数类型 参数名 ...
- 定位--position属性
一.定位--position属性 1.static:默认值 没有定位--以标准文档流方式显示 2.relative:相对定位--相对自身原来的位置进行偏移(top left right bottom) ...
- nginx之 nginx虚拟机配置
1.配置通过域名区分的虚拟机[root@mysql03 nginx]# cat conf/nginx.confworker_processes 1; events { worker_connectio ...
- css样式表的选择器与分类
css 样式表的作用: 主要用于结构,样式与行为,CSS主要的作用就是美化网页的一个语言,它的特点: 1.结构与样式分离的方式,便于后期维护与改版; 2.样式定义精确到像素的级别; css样式表的结构 ...
- 使用可视化图表对 Webpack 2 的编译与打包进行统计分析
此文主要对使用可视化图表对 Webpack 2 的编译与打包进行统计分析进行了详细地讲解,供您更加直观地参考. 在之前更新的共十七章节中,我们陆续讲解了 Webpack 2 从配置到打包.压缩优化到调 ...
- 在centos6.7中lnmp环境下安装swoole插件和pthreads插件
1.首先在安装lnmp集成包之前,解压lnmp1.3-full.tar.gz,进入到lnmp1.3-full/include/目录下; 2.输入 vi php.sh;编辑php.sh文档.博主安的是p ...