UVA-1220-Party at Hali-Bula

题意:

一个公司员工要举行聚会,要求任意一个人不能和他的直接上司同时到场,一个员工只有一个支系上司,现在求最多有多少人到场,并且方案是否唯一(紫书282页)

分析:

紫薯写的很清楚,而且也很基础,就不重复了,只做几点记录和总结

  • 输入中输入的是名字,每个名字要和一个id对应,当然最容易想到的就是map。但是还需要注意一点,就是不能保证输入的顺序,也就是说如果首先输入的父节点之前没有出现过,那么就没办法获取到父节点的id。建树时要考虑输入数据的顺序(或者是重复输入的)
  • 关于此题,因为要判断唯一性,所以不是单纯的树的最大独立点集问题。而新增的数组f,则可以很方便的把唯一性的状态储存下来。
#define maxn 210
vector<int> v[maxn];
map<string,int> M;
int n;
int ans,res;
int dp[maxn][2],f[maxn][2];
void dfs(int u)
{
dp[u][0] = 0;
dp[u][1] = 1;
f[u][0] = f[u][1] = 1;
int l = v[u].size();
//树形dp基本框架
for(int i=0;i<l;i++)
{
int y = v[u][i];
dfs(y);
dp[u][1] += dp[y][0];
if(f[y][0]==0)f[u][1] = 0; dp[u][0] += max(dp[y][0],dp[y][1]);
if(dp[y][0]==dp[y][1])f[u][0] = 0;
else if(dp[y][0]>dp[y][1]&&f[y][0]==0)f[u][0] = 0;
else if(dp[y][0]<dp[y][1]&&f[y][1]==0)f[u][0] = 0;
}
}
//获取对应id
int cnt;
int id(const string& str)
{
if(!M.count(str))
M[str] = ++cnt;
return M[str];
}
int main()
{
while(cin>>n)
{
if(n==0)break;
for(int i=1;i<=n;i++)
v[i].clear();
//ans储存人数,res保存是否唯一
ans = 0;res = 1;
M.clear();
cnt = 0;
string a,b;
cin>>a;
id(a);
//输入的坑点就在这里
for(int i=2;i<=n;i++)
{
cin>>a>>b;
v[id(b)].push_back(id(a));
//M[a] = i;这是之前错误的写法,因为我们不能保证M[b]一定存在。
//v[M[b]].push_back(M[a]);
}
dfs(1);
ans = max(dp[1][0],dp[1][1]);
if(dp[1][0]==dp[1][1]||(dp[1][0]>dp[1][1]&&f[1][0]==0)||(dp[1][0]<dp[1][1]&&f[1][1]==0))
res = 0;
printf("%d %s\n",ans,res==0?"No":"Yes");
}
return 0;
}

UVA-1218-Perfect Service

题意:

有n个机器组成的树形结构,要求一台服务器必须连接一台电脑,求使用的最少的服务器

分析

对于任意一个机器u,可以是服务器也可以不是服务器,由于有“不是服务器的机器必须恰好与一个服务器相邻”的条件,又由于它是一棵树,所以我们借用每个节点的父节点,来表示状态。即分为三种情况

  • u是服务器。那么与u管联的任何机器可以是服务器也可以不是
  • u不是服务器,u的父节点是服务器。那么u的所有子节点都不是服务器
  • u不是服务器,u的父节点不是服务器。那么u必须恰好有一个子节点是服务器

动态转移:

d[u][0] = sum{ min(d[v][0],d[v][1])}

d[u][1] = sum{d[v][2]}

d[u][2] = min(d[u][1]-d[v][2]+d[v][0])

第三个含义是这样的:因为要求v是服务器的情况的最小值,并且u的其他子节点都不是服务器。d[u][0]保存了u子节点都不是服务器的最优解,d[v][2]保存了v不是服务器的最优解,d[v][0]保存了v是服务器的最优解。所以有上述式子可得d[u][2]的最优解

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3fffffff
#define maxn 10010
vector<int> v[maxn];
int n,ans;
int d[maxn][3];
void dp(int x,int p)
{
d[x][0] = 1;
d[x][1] = 0;
d[x][2] = maxn;
int l = v[x].size();
for(int i=0;i<l;i++)
{
int y = v[x][i];
if(y==p)continue;
dp(y,x);
d[x][0] += min(d[y][0],d[y][1]);
d[x][1] += d[y][2];
}
//因为计算d[x][2]要用到d[x][1],而d[x][1]是累加计算,所以要分开两次遍历
for(int i=0;i<l;i++)
{
int y = v[x][i];
if(y==p)continue;
d[x][2] = min(d[x][2],d[x][1]-d[y][2]+d[y][0]);
}
}
int main()
{
while(~scanf("%d",&n)&&n!=-1)
{
if(n==0)continue;
for(int i=1;i<=n;i++)
v[i].clear();
int x,y;
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
}
dp(1,0);
//最后这里的坑点,想一想为什么没有d[1][1]呢?
ans = min(d[1][0],d[1][2]);
cout<<ans<<endl;
}
return 0;
}

UVA-1220-Party at Hali-Bula && UVA-1218-Perfect Service(树形DP)的更多相关文章

  1. UVA - 1218 Perfect Service(树形dp)

    题目链接:id=36043">UVA - 1218 Perfect Service 题意 有n台电脑.互相以无根树的方式连接,现要将当中一部分电脑作为server,且要求每台电脑必须连 ...

  2. UVA - 1218 Perfect Service (树形dp)(inf相加溢出)

    题目链接 题意:给你一个树形图,让你把其中若干个结点染成黑色,其余的染成白色,使得任意一个白色结点都恰好与一个黑色结点相邻. 解法比较容易,和树上的最大独立集类似,取一个结点作为树根,对每个结点分三种 ...

  3. UVa 1218 - Perfect Service

    /*---UVa 1218 - Perfect Service ---首先对状态进行划分: ---dp[u][0]:u是服务器,则u的子节点可以是也可以不是服务器 ---dp[u][1]:u不是服务器 ...

  4. UVa 1218 - Perfect Service(树形DP)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  5. UVA - 1218 Perfect Service (树形DP)

    思路:dp[i][0]表示i是服务器:dp[i][1]表示i不是服务器,但它的父节点是服务器:dp[i][2]表示i和他的父亲都不是服务器.       转移方程: d[u][0] += min(d[ ...

  6. UVa 1218 Perfect Service 完美的服务

    ***状态设计值得一看dp[u][0]表示u是服务器(以下v均指任意u的子结点,son指u的所有子结点)ap[u][0]=sum{dp[v][1]}+1//错误,服务器是可以和其他服务器相邻的dp[u ...

  7. POJ 3342 Party at Hali-Bula / HDU 2412 Party at Hali-Bula / UVAlive 3794 Party at Hali-Bula / UVA 1220 Party at Hali-Bula(树型动态规划)

    POJ 3342 Party at Hali-Bula / HDU 2412 Party at Hali-Bula / UVAlive 3794 Party at Hali-Bula / UVA 12 ...

  8. uva 1220

    1220 - Party at Hali-Bula Time limit: 3.000 seconds Dear Contestant, I'm going to have a party at my ...

  9. UVa 10859 - Placing Lampposts 树形DP 难度: 2

    题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...

  10. UVA - 11584 划分字符串的回文串子串; 简单dp

    /** 链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34398 UVA - 11584 划分字符串的回文串子串: 简单 ...

随机推荐

  1. web框架原理,http 协议

    目录 web框架原理 web框架是什么东西 执行代码用浏览器访问一下 输出结果 http 协议 http 协议简介 http 协议概述 http 工作原理 http请求方法 http 状态码 url介 ...

  2. Linux之expect非交互式功能

    我在上一篇博文linux之SSH密钥认证 提过ssh之间的相互认证,但是每次使用ssh登录到其它服务器还是要输入密码的. expect是用于提供自动交互的工具,自动连接被管理的服务器,不需要手动输入密 ...

  3. OFFICE 365 A1 Plus账号注册

    OFFICE365 A1 Plus账号注册 Office2019与Office365专业增强版之间的区别: Office2019是一次性购买,不会在购买后接收功能更新,但会根据需要接收质量和安全修补程 ...

  4. Cordova 系列之创建一个iOS项目

    1.打开终端 2.输入命令 $ cd Desktop (PS:Desktop表示放在桌面,你可以选择放任意位置) 3.$  cordova create HelloWorld com.example. ...

  5. JS高级学习历程-1

    JS高级-34-昨天内容回顾     时间:2015-5-11 1.DOM获取元素节点 document.getElenmentById(id 属性值)                         ...

  6. linux常用命令(ubuntu)

    编辑: vi [path] vim [path] :q 退出 :wq 保存退出 查看进程 ps ps -aux | grep mem 查看全部含 “mem”的进程 ps –aux  查看全部 在系统启 ...

  7. POJ-3275:Ranking the Cows(Floyd、bitset)

    Ranking the Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 3301   Accepted: 1511 ...

  8. sgu316Kalevich Strikes Back(线段树+扫描线)

    做法:总体想法是求出一个矩形的面积以及它所包含的矩形,然后用自己的面积减掉所包含的.主要问题是怎样求解它所包含的矩形. 因为是没有相交点的,可以利用扫描线的方法去做,类似染色,当前段如果是x色,也就是 ...

  9. django创建超级用户

    终端输入 python3 manage.py createsuperuser 按照提示进行操作即可 不输入用户名会给你默认一个用户名,输入密码是在原处不动的,其实已经在输入了. 创建超级用户是为了能够 ...

  10. selenium-Python之进行文件的上传和下载文件

    在利用Selenium进行批量上传文件时,遇到如下的Windows窗口进行上传.下载操作时,可以通过pywinauto进行操作.上传窗口如下 使用pywinauto,需知Windows窗口控件的cla ...