1. 题目描述
某树形网络由$n, n \in [1, 10^4]$台计算机组成。现从中选择一些计算机作为服务器,使得每当普通计算机恰好与一台服务器连接(并且不超过一台)。求需要指定服务器的最少数量

2. 基本思路
这显然是一个求最优解的问题,并且该网络拓扑结构为树形。因此,考虑树形DP。关键是考虑有哪些状态?不妨令
(1) $dp[u][0]$表示$u$作为服务器,那么它的儿子结点可以是服务器或者普通机;
(2) $dp[u][1]$表示$u$是普通计算机,但是$fa[u]$作为服务器,那么它的儿子结点一定是普通机;
(3) $dp[u][2]$表示$u$和$fa[u]$都是普通计算机,那么它的其中一个儿子结点是服务器。
因此,很容易推导状态转移。
\begin{align}
  dp[u][0] &= 1 + \sum \min (dp[v][0], dp[v][1])  \\
  dp[u][1] &= \sum dp[v][2] \\
  dp[u][2] &= \min (dp[v][0] - dp[v][2]) + \sum dp[v][2] \notag \\
           &= \min (dp[v][0] - dp[v][2]) + dp[u][1]
\end{align}
这里注意所求解是$\min (dp[rt][0], dp[rt][2])$,因为根节点没有父亲节点。这是树形DP中很经典的模型。

3. 代码

 /* 3398 */
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <bitset>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,1024000") #define sti set<int>
#define stpii set<pair<int, int> >
#define mpii map<int,int>
#define vi vector<int>
#define pii pair<int,int>
#define vpii vector<pair<int,int> >
#define rep(i, a, n) for (int i=a;i<n;++i)
#define per(i, a, n) for (int i=n-1;i>=a;--i)
#define clr clear
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1
#define INF 0x3f3f3f3f
#define mset(a, val) memset(a, (val), sizeof(a)) typedef struct {
int v, nxt;
} edge_t; const int maxv = ;
const int inf = 1e5;
const int maxe = maxv * ;
int head[maxv], l;
edge_t E[maxe];
int dp[maxv][];
int n; void init() {
memset(head, -, sizeof(head));
l = ;
} inline void addEdge(int u, int v) {
E[l].v = v;
E[l].nxt = head[u];
head[u] = l++; E[l].v = u;
E[l].nxt = head[v];
head[v] = l++;
} void dfs(int u, int fa) {
int k; dp[u][] = ;
dp[u][] = ;
dp[u][] = inf;
for (k=head[u]; k!=-; k=E[k].nxt) {
int& v = E[k].v;
if (v == fa)
continue;
dfs(v, u);
dp[u][] += min(dp[v][], dp[v][]);
dp[u][] += dp[v][];
dp[u][] = min(dp[u][], dp[v][]-dp[v][]);
} dp[u][] += dp[u][];
} void solve() {
dfs(, );
int ans = min(dp[][], dp[][]);
printf("%d\n", ans);
} int main() {
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif int u, v; while (scanf("%d",&n)!=EOF && n) {
init();
rep(i, , n) {
scanf("%d%d",&u,&v);
addEdge(u, v);
}
solve();
scanf("%d", &n);
if (n == -)
break;
} #ifndef ONLINE_JUDGE
printf("time = %ldms.\n", clock());
#endif return ;
}

【POJ】3398 Perfect Service的更多相关文章

  1. 【题解】UVA1218 Perfect Service

    UVA1218:https://www.luogu.org/problemnew/show/UVA1218 刷紫书DP题ing 思路 参考lrj紫书 不喜勿喷 d(u,0):u是服务器,孩子是不是服务 ...

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

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

  3. 【POJ】1704 Georgia and Bob(Staircase Nim)

    Description Georgia and Bob decide to play a self-invented game. They draw a row of grids on paper, ...

  4. 【POJ】1067 取石子游戏(博弈论)

    Description 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可以在两堆中同时取走相同数量的石子.最后 ...

  5. 【BZOJ1820】[JSOI2010]Express Service 快递服务 暴力DP

    [BZOJ1820][JSOI2010]Express Service 快递服务 Description 「飞奔」快递公司成立之后,已经分别与市内许多中小企业公司签订邮件收送服务契约.由于有些公司是在 ...

  6. 【BZOJ】【1986】【USACO 2004 Dec】/【POJ】【2373】划区灌溉

    DP/单调队列优化 首先不考虑奶牛的喜欢区间,dp方程当然是比较显然的:$ f[i]=min(f[k])+1,i-2*b \leq k \leq i-2*a $  当然这里的$i$和$k$都是偶数啦~ ...

  7. 【POJ】【2104】区间第K大

    可持久化线段树 可持久化线段树是一种神奇的数据结构,它跟我们原来常用的线段树不同,它每次更新是不更改原来数据的,而是新开节点,维护它的历史版本,实现“可持久化”.(当然视情况也会有需要修改的时候) 可 ...

  8. 【POJ】1222 EXTENDED LIGHTS OUT

    [算法]高斯消元 [题解] 高斯消元经典题型:异或方程组 poj 1222 高斯消元详解 异或相当于相加后mod2 异或方程组就是把加减消元全部改为异或. 异或性质:00 11为假,01 10为真.与 ...

  9. 【POJ】2892 Tunnel Warfare

    [算法]平衡树(treap) [题解]treap知识见数据结构 在POJ把语言从G++换成C++就过了……??? #include<cstdio> #include<algorith ...

随机推荐

  1. 【BZOJ】【1855】【SCOI2010】/【HDOJ】【3401】股票交易

    DP/单调队列优化 题解:http://www.cnblogs.com/jianglangcaijin/p/3799736.html 令f[i][j]表示第 i 天结束后,手里剩下 j 股的最大利润, ...

  2. 2-Highcharts 3D图之3D柱状图带可调试倾斜角度

    <!DOCTYPE> <html lang='en'> <head> <title>2-Highcharts 3D图之3D柱状图带可调试倾斜角度< ...

  3. HackPorts – Mac OS X 渗透测试框架与工具

    HackPorts是一个OS X 下的一个渗透框架. HackPorts是一个“超级工程”,充分利用现有的代码移植工作,安全专业人员现在可以使用数以百计的渗透工具在Mac系统中,而不需要虚拟机. 工具 ...

  4. CSS 类名的单词连字符:下划线还是连接符?

    本文的部分内容整理自我对此问题的解答: 命名 CSS 的类或 ID 时单词间如何连接? - 知乎 问题 CSS 类或 ID 命名时单词间连接通常有这几种写法: 驼峰式: solutionTitle.s ...

  5. code::blocks 初使用遇到的问题记录

    /* 做本程序遇到的问题:由于使用的是CODE::BLOCKS 开发环境,刚开始使用code::blocks是,什么都 没有设置,居然输入的中文字符串,保存项目后,再次打开,code::blocks不 ...

  6. Cortex-M3/4的Hard Fault调试方法

    1 Cortex-M3/4的Fault简介 Cortex-M3/4的Fault异常是由于非法的存储器访问(比如访问0地址.写只读存储位置等)和非法的程序行为(比如除以0等)等造成的.常见的4种异常及产 ...

  7. POJ 1496

    #include <iostream> #include <string> using namespace std; int fac(int num); int C(int n ...

  8. Javascript format方法

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  9. Linux中ping命令

    Linux系统的ping命令是常用的网络命令,它通常用来测试与目标主机的连通性,我们经常会说“ping一下某机器,看是不是开着”.不能打开网页时会说“你先ping网关地址192.168.1.1试试”. ...

  10. lintcode :First bad version 第一个错误的代码版本

    题目 第一个错误的代码版本 代码库的版本号是从 1 到 n 的整数.某一天,有人提交了错误版本的代码,因此造成自身及之后版本的代码在单元测试中均出错.请找出第一个错误的版本号. 你可以通过 isBad ...