题意:有N个点,N-1条边,任意两点可达,由此形成了一棵树。选取一个点a,它可覆盖自己以及与自己相邻的点,选取尽量少的点a,使得树中所有点都被覆盖,即求树的最小点支配集。

分析:

1、对于每一个点cur,要想使其被覆盖,有三种情况:

dp[cur][0]---在该点建立塔

dp[cur][1]---在该点的子结点建立塔

dp[cur][2]---在该点的父结点建立塔

2、对于点cur的子结点x,要使其被覆盖:

(1)dp[cur][0] += Min(Min(dp[x][0], dp[x][1]), dp[x][2]);

在cur处建塔的情况下,x可建塔,x的子节点可建塔,x的父结点即cur建塔,三者取最小值,并累加。

(2)dp[cur][2] += Min(dp[x][0], dp[x][1]);

在cur的父结点建塔的情况下,x可建塔,x的子结点可建塔,两者取最小值,并累加。

(3)dp[cur][1] += Min(dp[x][0], dp[x][1]);

在cur的子结点建塔的情况下,至少需要cur的一个子结点建塔cur才能被覆盖,所以对于每一个子结点x,x可建塔,x的子结点可建塔,两者取最小值

与此同时,记录在取最小值的情况下,cur是否有能建塔的子结点,若没有,需要将cur的一个子结点变成可建塔,选取abs(dp[x][1] - dp[x][0])最小的子结点x改变即可。

3、dp[cur][0]最后要加1,因为在cur点要建塔。

#pragma comment(linker, "/STACK:102400000, 102400000")
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<iostream>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#define Min(a, b) ((a < b) ? a : b)
#define Max(a, b) ((a < b) ? b : a)
const double eps = 1e-8;
inline int dcmp(double a, double b){
if(fabs(a - b) < eps) return 0;
return a > b ? 1 : -1;
}
typedef long long LL;
typedef unsigned long long ULL;
const int INT_INF = 0x3f3f3f3f;
const int INT_M_INF = 0x7f7f7f7f;
const LL LL_INF = 0x3f3f3f3f3f3f3f3f;
const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f;
const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1};
const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1};
const int MOD = 1e9 + 7;
const double pi = acos(-1.0);
const int MAXN = 10000 + 10;
const int MAXT = 10000 + 10;
using namespace std;
int N;
vector<int> v[MAXN];
int dp[MAXN][5];
void dfs(int cur, int father){
memset(dp[cur], 0, sizeof dp[cur]);
int len = v[cur].size();
int dif = INT_INF;
bool ok = false;
for(int i = 0; i < len; ++i){
int x = v[cur][i];
if(x == father) continue;
if(dp[x][0] == INT_INF) dfs(x, cur);
dp[cur][0] += Min(Min(dp[x][0], dp[x][1]), dp[x][2]);
dp[cur][2] += Min(dp[x][0], dp[x][1]);
dif = Min(dif, abs(dp[x][1] - dp[x][0]));
if(dp[x][0] < dp[x][1]){
ok = true;
dp[cur][1] += dp[x][0];
}
else{
dp[cur][1] += dp[x][1];
}
}
++dp[cur][0];
if(!ok) dp[cur][1] += dif;
}
int main(){
scanf("%d", &N);
for(int i = 0; i < N - 1; ++i){
int a, b;
scanf("%d%d", &a, &b);
v[a].push_back(b);
v[b].push_back(a);
}
memset(dp, INT_INF, sizeof dp);
dfs(1, -1);
printf("%d\n", Min(dp[1][0], dp[1][1]));
return 0;
}

  

POJ - 3659 Cell Phone Network(树形dp---树的最小点支配集)的更多相关文章

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

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

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

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

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

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

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

    最小支配集: 从V中选取尽量少的点组成一个集合,让V中剩余的点都与取出来的点有边相连. (点) 最小点覆盖: 从V中选取尽量少的点组成一个集合V1,让所有边(u,v)中要么u属于V1,要么v属于V1 ...

  5. POJ 3659 Cell phone Network (树的最小点覆盖, 树形DP)

    题意: 给定一棵树,每个点可以覆盖自己和相邻的点, 求最少要多少个点覆盖图 #include <cstdio> #include <cstring> #include < ...

  6. POJ 3659 Cell Phone Network (树dp)

    题目链接:http://poj.org/problem?id=3659 给你一个树形图,一个点可以覆盖他周围连接的点,让你用最少的点覆盖所有的点. dp[i][0]表示用i点来覆盖,dp[i][1]表 ...

  7. POJ 3342 Party at Hali-Bula (树形dp 树的最大独立集 判多解 好题)

    Party at Hali-Bula Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5660   Accepted: 202 ...

  8. 树形DP+树状数组 HDU 5877 Weak Pair

    //树形DP+树状数组 HDU 5877 Weak Pair // 思路:用树状数组每次加k/a[i],每个节点ans+=Sum(a[i]) 表示每次加大于等于a[i]的值 // 这道题要离散化 #i ...

  9. [HDU 5293]Tree chain problem(树形dp+树链剖分)

    [HDU 5293]Tree chain problem(树形dp+树链剖分) 题面 在一棵树中,给出若干条链和链的权值,求选取不相交的链使得权值和最大. 分析 考虑树形dp,dp[x]表示以x为子树 ...

随机推荐

  1. windows目标进程注入dll

    在别的程序注入dll 步骤: ,获取目标进程ID,CreateToolhelp32Snapshot()函数; ,获取目标进程句柄,OpenProcess()函数; ,目标进程要一块内存,Virtual ...

  2. APM概述

    当前 APM(Application Performance Management (Monitoring)/ 应用性能管理)或者叫 Distributed Tracing System 工具有: G ...

  3. vue table已选列数据

    vue Table@on-selection-change="test" 已选中项数据 test(selection){} <Table :data="tableD ...

  4. Day6 - G - 立方体大作战tet HYSBZ - 1106

    一个叫做立方体大作战的游戏风靡整个Byteotia.这个游戏的规则是相当复杂的,所以我们只介绍他的简单规则:给定玩家一个有2n个元素的栈,元素一个叠一个地放置.这些元素拥有n个不同的编号,每个编号正好 ...

  5. linux 查看ip、用户、时间对应执行的命令

    这个需要使用到history命令.可以加数字,返回最近执行的几条命令.如果不加数字会返回所有的历史命令. [root@localhost ~]# history 20 1015 rm stdin.lo ...

  6. SpringBoot---条件(th:if)

    Thymeleaf 的条件判断是 通过 th:if 来做的,只有为真的时候,才会显示当前元素 <p th:if="${testBoolean}" >如果testBool ...

  7. Jupyter Notebooks usage

    Important note: You should always work on a duplicate of the course notebook. On the page you used t ...

  8. C. Basketball Exercise dp

    C. Basketball Exercise time limit per test 2 seconds memory limit per test 256 megabytes input stand ...

  9. php 和 文本编辑器火狐的配置

    个人比较习惯的编辑器和浏览器配置 Sublime Ctrl+Shitf+P 输入 install 安装扩展: 点开菜单 -> view -> showConsole (或者按住 Ctrkl ...

  10. 51nod:天堂里的游戏

    天堂里的游戏 李陶冶 (命题人) System Message (测试) 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 多年后,每当Noder看到吉普赛人,就会想起那个遥远的下午. ...