【Link】:

【Description】



给你n个机器组成的一棵树,然后,让你在某些机器上安装服务器.

要求,每个机器如果没有安装服务器,都要恰好和一个安装了服务器的机器连接.

问你,最少要安装多少个服务器

【Solution】



比较常见的树形DP

f[i][0]表示,i这个节点没装服务器,然后i这个节点没被儿子节点中的某一个控制,且儿子节点都已经符合要求的的最小服务器数.

f[i][1]表示,i这个节点没装服务器,然后i这个节点被儿子节点中的某一个控制,且i以下的节点都已经符合要求的最小服务器个数.

h[i]表示,i这个节点装了服务器,且以下的节点都已经符合要求的最小服务器个数.

转移的时候

(以下,j都为i的儿子节点)

f[i][0]=∑f[j][1]

h[i]=∑max(h[j],f[j][0])

f[i][1]=∑f[j][1]+h[idx]−f[idx][1]

这里的idx是i的儿子节点中h的值最小的那个;

表示要选一个儿子节点装上服务器,来控制这个i节点.

对于叶子节点cnt

f[cnt][0]=0,f[cnt][1] = INF,h[cnt] = 1;

这里如果某个时刻,∑f[j][1] >= INF,则说明i节点会是倒数第二层的节点;

则可以在最底层中的某一个装服务器,则直接把f[i][1]赋值为h[idx][1]就好;

左边的∑符号里的东西可以省去了。

加的时候可能会超int,所以大于INF了就变成INF



【NumberOf WA】



1



【Reviw】



这道题的数据挺水的。。



【Code】

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ms(x,y) memset(x,y,sizeof x)
#define Open() freopen("D:\\rush.txt","r",stdin)
#define Close() ios::sync_with_stdio(0) typedef pair<int,int> pii;
typedef pair<LL,LL> pll; const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);
const int N = 10000;
const int INF = 0x3f3f3f3f; int n,f[N+100][2],h[N+100]; vector <int> g[N+100]; void limit(int &x){
x = min(x,INF);
} void dfs(int x,int fa){
if (x!=1 && (int) g[x].size() == 1){
f[x][0] = 0;
f[x][1] = INF;
h[x] = 1;
return;
}
//f[i][0],没放服务器,没被控制,最小服务器个数
//f[i][1],没放服务器,被控制了,最小服务器个数
//h[i],放了服务器,且下面都被合法控制,最小服务器个数
f[x][0] = f[x][1] = 0;
h[x] = 1;
int len = (int) g[x].size();
int mi = INF,idx = 0;
rep1(i,0,len-1){
int y = g[x][i];
if (y==fa) continue;
dfs(y,x);
if (h[y] < mi){
mi = h[y];
idx = y;
}
f[x][0] += f[y][1];
limit(f[x][0]);
f[x][1] += f[y][1];
limit(f[x][1]);
h[x] += min(f[y][0],h[y]);
limit(h[x]);
}
if (f[x][1]>=INF){
f[x][1] = h[idx];
}else{
f[x][1] -= f[idx][1];
f[x][1] += h[idx];
}
limit(f[x][1]);
} int main(){
//Open();
//Close();
int t = 0;
while (t==0){
rep1(i,1,N) g[i].clear();
scanf("%d",&n);
rep1(i,1,n-1){
int x,y;
scanf("%d%d",&x,&y);
g[x].pb(y),g[y].pb(x);
}
dfs(1,0);
printf("%d\n",min(h[1],f[1][1]));
scanf("%d",&t);
if (t==-1) break;
}
return 0;
}

最新文章

  1. linux内核学习之三 跟踪分析内核的启动过程
  2. 转载:学习Entity Framework 中的Code First
  3. bzoj2683简单题
  4. Android学习笔记(七)——常见控件
  5. 【python】编码规范(转载)
  6. HDU 4393 Throw nails
  7. alibaba笔试1
  8. Git上手指南
  9. Linux系统查找
  10. JAVAEE——BOS物流项目01:学习计划、搭建环境、主页设计(jQuery EasyUI)
  11. 微信小程序爬坑
  12. Mysql ssl 连接
  13. 关于vue的混入使用
  14. sql server 2014登录账号
  15. 获取当前iframe动态加载文档的href
  16. Ubuntu 16.04 grub rescue 模式下修复 grub
  17. Matlab当中size() length()等函数讲解
  18. leetcode942
  19. &lt;meta name=&quot;renderer&quot; content=&quot;webkit&quot;&gt;
  20. Mapper.xml映射文件

热门文章

  1. HDU1285-确定比赛名次-拓扑排序板子题
  2. 【LGP5439】【XR-2】永恒
  3. 2018湘潭大学程序设计竞赛【B】
  4. scrapy不抓取重复的网页解决办法
  5. arm-linux-readelf 的使用
  6. c结构体指针使用
  7. protobuf文档翻译-安装,数据格式及编码规范
  8. JedisCluster获取key所在的节点
  9. 【JZOJ6376】樱符[完全墨染的樱花]
  10. Windows netstat