UVa 1220 Party at Hali-Bula dp:树的最大独立集

UVA - 1220
Party at Hali-Bula
Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu

Submit Status


The question is from here.


My Solution

注意点:这个题目有些测试数据是先出现father再出现son的,如

5

jack

jill black

black jack

kar pur

pur black


树的最大独立集问题,扩充到要判定唯一性

状态:d[u][0]表示以u为根的子树中,不选u点能得到的最大人数;f[u][0]为方案唯一性,1为唯一0为不唯一;

相应的有d[u][1],f[u][1]表示选u是的情况


转移:d[u][1]选u则子节点不选,d[u][1] = sum{ d[v][0] | v是u的子节点} 当且仅当f[v][0]全为1是f[u][1]才是1;

          d[u][0]因为u没有选,所以每个子结点v可以选也可以不选,即 d[u][0] = sum{  max(d[v][0], d[v][1]) } 

     如果某个地方d[v][0] == d[v][1] 则不唯一。另外,如果取到最大的那个值为0,则也不唯一;

          对d[0][0]与d[0][1] 输出最大值后,也要最后判断下这2个是否相等;


边界:f[u][1] = f[u][0] = 1;默认当然是要1的

           d[u][0] = 0;当次没选就自己这个结点不算了,

   d[u][1] = 1;


算法:dfs,一层一层下去,直到叶子,然后分别填好 子结构 的 四个状态值;


#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
//#define LOCAL
using namespace std;
const int maxn = 208;

vector<int> sons[maxn];
map<string,int> id;
int d[maxn][2],f[maxn][2];

void dfs(int u)
{
    f[u][0] = f[u][1] = 1;          //setting the edge
    d[u][0] = 0;d[u][1] = 1;
    int sz = sons[u].size(),v;
    for(int i = 0; i < sz; i++){
        v = sons[u][i];
        dfs(v);

        d[u][1] += d[v][0];
        f[u][1] &= f[v][0];

        d[u][0] += max(d[v][0], d[v][1]);
        if(d[v][0] == d[v][1]) f[u][0] = 0;
        else f[u][0] &= (d[v][0] > d[v][1]) ? f[v][0] : f[v][1];
    }
}

int main()
{
    #ifdef LOCAL
    freopen("a.txt","r",stdin);
    #endif // LOCAL
    int n;
    string emp,boss;
    while(scanf("%d", &n) && n){
        cin>>boss;
        id[boss] = 0;
        for(int i = 1, j = 1; i < n; i++){
            cin>>emp>>boss;  if(!id.count(emp)) id[emp] = j++;
            if(!id.count(boss)) id[boss] = j++;
            //!an employee will only show in emp a time ,we need count() it;
            sons[id[boss]].push_back(id[emp]);
        }
        dfs(0);
        printf("%d ", max(d[0][0], d[0][1]));
        if(d[0][0] == d[0][1]) puts("No");              //! need the outest judge whether d[0][0] == d[0][1]
        else if((d[0][0] > d[0][1]) ? f[0][0] : f[0][1]) puts("Yes");
        else puts("No");                                //this "else" can't be eliminated.
        //reset
        for(int i = 0; i < n; i++)
            sons[i].clear();
        id.clear();
    }
    return 0;
}

Thank you all!


你可能感兴趣的:(dp,动态规划,ACM,uva,树的最大独立集)