博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【uva】1220 Party at Hali-Bula
阅读量:7051 次
发布时间:2019-06-28

本文共 3255 字,大约阅读时间需要 10 分钟。

1. 题目描述

公司里有$n, n \in [1, 200]$个人,他们间的关系构成树状结构。除老板外,每个员工都有唯一一个直属上司,要求从中选择尽量多的人,但是不能同时选择员工和他的直属上司,问最多能选多少人,以及可行解是否是唯一的?
2. 基本思路
这显然又是一个树形DP的题目,经典模型——树的最大独立集。《算法竞赛入门经典》中的典型例题,唯一稍微不同的是需要判断可行解是否唯一。因此,先分析状态:
(1) $dp[u][0]$表示不选$u$的最大人数,$f[u][0]$表示当前选择是否唯一,此时可以选择、也可以不选择$u$的下属;
(2) $dp[u][1]$表示选择$u$的最大人数,$f[u][1]$表示当前选择是否唯一,此时一定不能选择$u$的下属;
可以很容易推导状态转移方程:
\begin{align}
    dp[u][0] &= \sum \max (dp[v][0], dp[v][1])  \\
    f[u][0]  &=  \bigwedge \Big( (dp[v][0] \neq dp[v][1]) \wedge f[v][dp[v][0] < dp[v][1]] \Big) \\
    dp[u][1] &= \sum dp[v][0]   \\
    f[u][1]  &= \bigwedge f[v][0]
\end{align}
可以使用刷表法进行实现这个DP,经典的树形DP模型。
3. 代码

1 /* uva1220 */  2 #include 
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include
15 #include
16 #include
17 #include
18 #include
19 #include
20 #include
21 #include
22 #include
23 #include
24 using namespace std; 25 //#pragma comment(linker,"/STACK:102400000,1024000") 26 27 #define sti set
28 #define stpii set
> 29 #define mpii map
30 #define vi vector
31 #define pii pair
32 #define vpii vector
> 33 #define rep(i, a, n) for (int i=a;i
=a;--i) 35 #define clr clear 36 #define pb push_back 37 #define mp make_pair 38 #define fir first 39 #define sec second 40 #define all(x) (x).begin(),(x).end() 41 #define SZ(x) ((int)(x).size()) 42 #define lson l, mid, rt<<1 43 #define rson mid+1, r, rt<<1|1 44 #define INF 0x3f3f3f3f 45 #define mset(a, val) memset(a, (val), sizeof(a)) 46 47 const int maxn = 205; 48 vi E[maxn]; 49 int fa[maxn]; 50 int dp[maxn][2]; 51 bool f[maxn][2]; 52 int n; 53 int pid; 54 map
tb; 55 map
::iterator iter; 56 57 void init() { 58 rep(i, 0, n+1) { 59 E[i].clr(); 60 fa[i] = 0; 61 } 62 tb.clr(); 63 pid = 1; 64 memset(dp, 0, sizeof(dp)); 65 memset(f, true, sizeof(f)); 66 } 67 68 inline void addEdge(int u, int v) { 69 fa[v] = u; 70 E[u].pb(v); 71 } 72 73 inline int findId(const string& s) { 74 int ret; 75 76 iter = tb.find(s); 77 if (iter == tb.end()) { 78 tb[s] = ret = pid++; 79 } else { 80 ret = iter->sec; 81 } 82 83 return ret; 84 } 85 86 void dfs(int u) { 87 int sz = SZ(E[u]), v; 88 89 dp[u][1] = 1; 90 rep(i, 0, sz) { 91 v = E[u][i]; 92 dfs(v); 93 } 94 95 // choose fa[u] choose u 96 dp[fa[u]][1] += dp[u][0]; 97 f[fa[u]][1] &= f[u][0]; 98 99 // not choose fa[u], choose or not u100 dp[fa[u]][0] += max(dp[u][0], dp[u][1]);101 f[fa[u]][0] &= (dp[u][0]!=dp[u][1]) & (f[u][dp[u][0]
dp[1][1])108 printf("%d %s\n", dp[1][0], f[1][0]?"Yes":"No");109 else if (dp[1][0] < dp[1][1])110 printf("%d %s\n", dp[1][1], f[1][1]?"Yes":"No");111 else112 printf("%d No\n", dp[1][1]);113 }114 115 int main() {116 ios::sync_with_stdio(false);117 #ifndef ONLINE_JUDGE118 freopen("data.in", "r", stdin);119 freopen("data.out", "w", stdout);120 #endif121 122 string su, sv;123 int uid, vid;124 125 while (cin>>n && n) {126 init();127 cin >> su;128 findId(su);129 rep(i, 1, n) {130 cin >> sv >> su;131 132 uid = findId(su);133 vid = findId(sv);134 addEdge(uid, vid);135 }136 solve();137 }138 139 #ifndef ONLINE_JUDGE140 printf("time = %ldms.\n", clock());141 #endif142 143 return 0;144 }

 

转载于:https://www.cnblogs.com/bombe1013/p/5336691.html

你可能感兴趣的文章
关于Git bash-127.0.0.7:8888拒绝访问的小问题--环境变量
查看>>
Java EE(七)
查看>>
javascript变量声明提升(hoisting)
查看>>
有价值的数据
查看>>
LayUi超级好用的前端工具
查看>>
[Ubuntu] ubuntu的tty下挂载移动硬盘拷贝数据
查看>>
PowerBI分析个人Exchange邮箱数据
查看>>
犯了个低级错误
查看>>
Win7部署基础知识(7):使用Imagex捕获和安装映像
查看>>
Outlook Anywhere 客户端配置详解
查看>>
IOS在Xcode 4.x以上如何 创建 和 添加 静态库
查看>>
WebSphere was 7.0修改端口号为80,修改上下文根
查看>>
Repeater控件数据导出Excel
查看>>
下载Android源码出现的问题
查看>>
远程桌面如何复制本地文件 远程桌面拷贝电脑上的文件方法
查看>>
[转]解决JS浮点数(小数)计算加减乘除的BUG
查看>>
ASP.NET MVC应用程序的安全性介绍总括(高级编程)
查看>>
Java模拟Delegate
查看>>
记录下,我们平时开发当中不得不知道的HTTP状态码
查看>>
HDU-1045 Fire NetFire Net 最大团
查看>>