Party at Hali-Bula(UVA

来源:互联网 发布:经典数据新闻案例分析 编辑:程序博客网 时间:2024/05/29 15:30


转载链接:http://blog.csdn.net/u014800748/article/details/43834351

这是我树形dp做的第一道题,这位博主对于解释和代码都写的非常详细,对于我这树形dp新入门的小白也能看懂,非常推荐!



一、解题思路:本题几乎就是树的最大独立集问题,只不过多了一个判断解的唯一性的要求。针对这种情况,可以做如下定义:

(1)d(u,0),f(u,0)分别表示以u为根的子树中,不选u点的最大人数和方案的唯一性(f=1表示唯一,f=0表示不唯一);

(2)d(u,1),f(u,1)分别表示以u为根的子树中,选u点的最大人数和方案的唯一性(f=1表示唯一,f=0表示不唯一);

相应的,状态转移方程也要有两种情况:

(1)d(u,1)的计算:由于选择了u,那么u的子结点都不能选。因此,d(u,1)=sum{d(v,0)|v是u的子结点}。当且仅当所有的f(v,0)=1时,f(u,1)才是1.

(2)d(u,0)的计算:因为u没有选,因此它的子结点可选可不选。因此,d(u,0)=sum{max(d(v,0),d(v,1))}。公式中先找到每个子结点的最大值,再求和。唯一性的判断:(i)如果d(v,0)==d(v,1),那么方案不唯一;(ii)如果max取到的那个结点的f=0,方案也不唯一。



二、附代码


#include<iostream>  #include<algorithm>  #include<string>  #include<sstream>  #include<set>  #include<vector>  #include<stack>  #include<map>  #include<queue>  #include<deque>  #include<cstdlib>  #include<cstdio>  #include<cstring>  #include<cmath>  #include<ctime>  #include<functional>  using namespace std;    #define maxn 200+10  int d[maxn][2];  int f[maxn][2];  map<string, int>IDcache;  vector<string>name;  vector<int>boss[maxn];  int n;  int ID(string s)  {      if (IDcache.count(s))          return IDcache[s];      name.push_back(s);      return IDcache[s] = name.size() - 1;  }  int is_unique(int d1, int d2, int f1, int f2)//判断方案是否唯一  {      if (d1 == d2)return 0;      else return (d1 > d2) ? f1 : f2;  }  int dp(int id, int flag)//根据flag分类讨论  {      int&ans = d[id][flag];      if (ans >= 0)return ans;      ans = 0;      if (flag)      {          if (boss[id].empty()){ f[id][flag] = 1; return ans = 1; }          int k = boss[id].size();          int ok = 1;          for (int i = 0; i < k; i++)          {              ans += dp(boss[id][i], 0);              if (f[boss[id][i]][0] != 1)                  ok = 0;          }          ans++;          if (ok)f[id][flag] = 1;          else f[id][flag] = 0;      }      else      {          if (boss[id].empty()){ f[id][flag] = 1; return ans = 0; }          int k = boss[id].size();          int ok = 1;          for (int i = 0; i < k; i++)          {              int d1 = dp(boss[id][i], 0);              int d2 = dp(boss[id][i], 1);              int tmp = max(d1, d2);              ans += tmp;              if (!is_unique(d1, d2, f[boss[id][i]][0], f[boss[id][i]][1]))                  ok= 0;          }          if (ok)f[id][flag] = 1;          else f[id][flag] = 0;      }      return ans;  }  int main()  {       while (scanf("%d", &n)&& n)      {          name.clear();          IDcache.clear();//注意每次重新使用时清空name,IDcache          memset(d, -1, sizeof(d));          memset(f, 0, sizeof(f));          memset(boss, 0, sizeof(boss));          string s, t;          cin >> s;          int id = ID(s);          for (int i = 1; i < n; i++)          {              cin >> s >> t;              int d1 = ID(s), d2 = ID(t);              boss[d2].push_back(d1);          }          int ans, ff;          int d1 = dp(id, 0);          int d2 = dp(id, 1);          ans = max(d1, d2);          if (!is_unique(d1, d2, f[id][0], f[id][1]))              ff = 0;          else ff = 1;          printf("%d %s\n", ans, ff ? "Yes" : "No");      }      return 0;  }  

原创粉丝点击