【题目描述】
太平王世子事件后,陆小凤成了皇上特聘的御前一品侍卫。
皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状,某些宫殿间可以互相望见。大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全天候看守,在不同的宫殿安排看守所需的费用不同。
可是陆小凤手上的经费不足,无论如何也没法在每个宫殿都安置留守侍卫。
帮助陆小凤布置侍卫,在看守全部宫殿的前提下,使得花费的经费最少。

【输入】
输入中数据描述一棵树,描述如下:第一行n,表示树中结点的数目。
第二行至第n+1行,每行描述每个宫殿结点信息,依次为:该宫殿结点标号i0 <isn),在该官殿安置侍卫所需的经费k,该边的儿子数m,接下来m个数,分别是这个节点的m个儿子的标号n,r, …,"rm
对于一个n个结点的树,结点标号在1到n之间,且标号不重复。
【输出】
输出最少的经费


最小支配集定义:在一个图G<V,E> 中,我们选取尽可能少的 点形成一个点集合 V ′ V' V′, 使在图G中的点要么在V’ 总要么与 V ′ V' V′中的点直接相连。

思路一——贪心求解

  1. 这一题明显是让求最小支配集的,
  2. 用贪心求解的话,首先预处理从根节点出发 dfs 一遍,按 dfs 访问到每个节点时候的顺序给每个节点编号,并统计上每个节点的父节点是那个节点,
  3. 之后按编号从到小的顺序,遍历每一个节点,我们用 s [i]==0 表示 i 节点没有被覆盖 ,
  4. 如果当前节点 s [v] == 1 , continue;
  5. 如果当前节点 s [v] == 0, 并且 v 的父节点 u 也没有在我们的支配集中,那么我们就把 u 添加到支配集中,并且标记 u 的父节点(设为 x)s [x]=1,
  6. 之后继续循环 3 步骤,
#include <bits/stdc++.h>using namespace std;
const int maxn = 1000;
int pre[maxn];//存储父节点
bool visit[maxn];//DFS标记数组
int newpos[maxn];//遍历序列
int now;
int n, m;int head[maxn];//链式前向星
struct Node {int to; int next;};
Node edge[maxn];void DFS(int x) {newpos[now ++] = x;//记录遍历序列for(int k = head[x]; k != -1; k = edge[k].next) {if(!visit[ edge[k].to ]) {visit[ edge[k].to ] = true;pre[edge[k].to] = x;//记录父节点DFS(edge[k].to);}}
}int MDS() {bool s[maxn] = {0};bool set[maxn] = {0};int ans = 0;for(int i = n - 1; i >= 0; i--) {//逆序进行贪心int t = newpos[i];if(!s[t]) { //如果当前点没被覆盖if(! set[ pre[t] ]) {//当前点的父节点不属于支配集set[ pre[t] ] = true;//当前点的父节点加入支配集ans ++;  //支配集节点个数加 1}s[t] = true; //标记当前点已被覆盖s[ pre[t] ] = true;// 标记当前点的父节点被覆盖s[ pre[ pre[t] ] ] = true;//标记当前点的父节点的父节点被覆盖}}return ans;
}int main() {/* read Graph message*/ //建图memset(visit, false, sizeof(visit));//初始化now = 0;visit[1] = true;pre[1] = 1;DFS(1);//从根节点开始寻摘遍历序列MDS();return 0;
}

思路二——树形DP

  1. 定义:dp

    1. dp [x][0] 表示当前节点 x 由父节点来看守
    2. dp [x][1] 表示当前节点 x 由子节点来看守
    3. dp [x][2] 表示我们在当前节 x 点放置一个守卫来看守,
  2. 状态转移方程
//如果当前节点 被父节点来看守的话 那么 在u这个节点 无论是否有收尾都行,所以dp[u][0] 从 dp[v][1]、 dp[v][2] 两者小的那个状态转移
dp[u][0] += min(dp[v][1], dp[v][2]);//如果当前节点 u这个点,我们自己放置一个守卫来看守, 那么可以从dp[v][0]、dp[v][1]、 dp[v][2] 中之最小的那个状态进行转移
dp[u][2] += Min(dp[v][0], dp[v][1], dp[v][2]);//sum 的值为所有子节点vi 的min(dp[vi][1], dp[vi][2])的之和
sum += min(dp[v][1], dp[v][2]);  //如果u由子节点为v来看守,由于u有多个子节点v1、v2...vm,我们可以依次指定让子节点v来看守,其它节子点(设为vi 并且 vi != x)是否有看守都无所谓(因此从这些子节点的转移的状态是:min(dp[vi][1], dp[vii][2]),因为我们已经指定了当前v节点必须来看守u,那从v节点进行的状态转移必须是:dp[v][2],
dp[u][1] = min(dp[u][1], sum - min(dp[v][1], dp[v][2]) + dp[v][2]);

代码

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <string>
#include <queue>
#include <map>
/* #include <unordered_map> */
#include <bitset>
#include <vector>
void fre() { system("clear"), freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { system("clear"), freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long
#define db double
#define Pir pair<int, int>
#define m_p make_pair
#define INF 0x3f3f3f3f
#define esp 1e-7
#define for_(i, s, e) for(int i = (ll)(s); i <= (ll)(e); i ++)
#define rep_(i, e, s) for(int i = (ll)(e); i >= (ll)(s); i --)
#define sc scanf
#define pr printf
#define sd(a) scanf("%d", &a)
#define ss(a) scanf("%s", a)
#define size() size() * 1LL
#define mod (ll)(10007)
#define Min(a, b, c) min(a, min(b, c))
#define Max(a, b, c) max(a, max(b, c))
using namespace std;const int mxn = 2e3;
vector<int> e[mxn];
int w[mxn];
int dp[mxn][3];void dfs(int u, int p)
{dp[u][2] = w[u];int sum = 0;for_(i, 0, e[u].size() - 1){int v = e[u][i];if(v == p) continue;dfs(v, u);dp[u][0] += min(dp[v][1], dp[v][2]);dp[u][2] += Min(dp[v][0], dp[v][1], dp[v][2]);sum += min(dp[v][1], dp[v][2]);}dp[u][1] = INF;for_(i, 0, e[u].size() - 1){int v = e[u][i];if(v == p) continue;dp[u][1] = min(dp[u][1], sum - min(dp[v][1], dp[v][2]) + dp[v][2]);}
}int main()
{/* fre(); */int n; sd(n);int u, x, t, v;for_(i, 1, n){sc("%d %d %d", &u, &x, &t);w[u] = x;for_(j, 1, t){sd(v);e[u].pb(v);e[v].pb(u);}}dfs(1, 0);pr("%d\n", min(dp[1][1], dp[1][2]));return  0;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

  7. *【POJ - 3659】Cell Phone Network (树形dp,最小支配集)

    题干: Farmer John has decided to give each of his cows a cell phone in hopes to encourage their social ...

  8. 最小函数依赖集的求解过程

    流程 ①先拆右边,假如依赖集F中的右边项包含不止一个属性,那么将这些项都拆为单个项.例如A->BC,拆分为A->B和A->C ②去除冗余依赖项,例如A->C和AB->C, ...

  9. poj 3398 (树上的最小支配集)

    入门题吧... Perfect Service Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 1220   Accepted ...

最新文章

  1. 【自动驾驶】12.百度Apollo对ROS的优化【详细干货】
  2. 关于eclipse的实用技巧
  3. Kali渗透测试——WOL-E
  4. 64位 int 占几个字节_面试常考,项目易错,长文详解C/C++中的字节对齐
  5. zookeeper版本更新_zookeeper介绍及运维实践
  6. windows server2012在已有.net4.5框架的基础上安装.net3.5的方法
  7. 用python做时间序列预测一:初识概念
  8. 【基础】位与运算与取余
  9. python敏感字替换_python实现敏感词过滤的几种方法
  10. python用cartopy包画地图_利用Cartopy绘制带有地图投影的图形
  11. 谷歌或Edge浏览器在开始菜单页面不显示图标
  12. Leetcode︱448. Find All Numbers Disappeared in an Array找到所有数组中消失的数字.java
  13. Effective java学习笔记
  14. Java输入时间输出热量卡路里的小程序
  15. 「NFT 之王」无聊猿与品牌的跨界营销!
  16. PCIe学习笔记之pcie初始化枚举和资源分配流程代码分析
  17. mysql存储过程default的意思,针对新手的MYSQL存储过程详解
  18. 服了,攻城狮的酒后真言竟然是这些?
  19. HTML设计美观的菜单栏
  20. 项目文件模板-项目实施变更申请表

热门文章

  1. python tcp server传输成功之后进行删除_Python第十课 网络管理
  2. linux终端复制粘贴快捷键。
  3. OpenGL中平移函数glTranslatef()、旋转函数glRotatef()的理解(非常好的文章)
  4. 华三交换机如何设置时间
  5. cookie实现登录功能
  6. 从失败中笑看数仓:探索构建数仓失败的原因
  7. php生成国密验证,PHP+gmssl命令行实现国密加解密
  8. 工程师是需要创造力的艺术家
  9. vue项目中draggable实现拖拽排序
  10. hbase查询列表数据返回rowKey