uva1220--树的最大独立集+判重

题意是挑选尽量多的人,并且每个人都不和他的父节点同时出现,很明显的最大独立集问题,难点在于如何判断方案是否唯一。

详情请见刘汝佳《算法竞赛入门经典--第二版》P282

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#include<cmath>
#include<queue>
#define INF 1e6
using namespace std;
const int maxn = 205;

char ch[105],fa[105];
char trie[maxn][105];
int k;
int d[maxn][2],f[maxn][2];
vector<int> g[maxn];

int ID(char *s)//给每个字符串分配ID;
{
    int i = 0;
    for(i = 0; i < k; ++i)
    {
        if(strcmp(s,trie[i]) == 0) {
            return i;
        }
    }
    if(i == k) strcpy(trie[k],s);
    k++;
    return k-1;
}
int dp(int u,int x)
{
    if(d[u][x]!=-1) return d[u][x];//记忆化
    if(x == 1){
        int sum = 1;
        f[u][1] = 1;
        if(g[u].size() == 0) return d[u][1] = 1;
        for(int i = 0; i < g[u].size(); ++i)
        {
            sum+=dp(g[u][i],0);
            if(f[g[u][i]][0] == 0) {
                f[u][1] = 0;
            }
        }
        return d[u][1] = sum;
    }
    else
    {
        int sum = 0;
        f[u][0] = 1;
        if(g[u].size() == 0) return d[u][0] = 0;
        for(int i = 0; i < g[u].size(); ++i)
        {
            int p = dp(g[u][i],0),q = dp(g[u][i],1);
            if(p == q)
            {
                sum+=p;
                f[u][0] = 0;
            }
            else if(p > q)
            {
                sum+=p;
                if(f[g[u][i]][0] == 0) f[u][0] = 0;
            }
            else if(p < q)
            {
                sum+=q;
                if(f[g[u][i]][1] == 0) f[u][1] = 0;
            }
        }
        return d[u][0] = sum;
    }
}
int main()
{
    //freopen("in","r",stdin);
    int n;
    while(~scanf("%d",&n)&&n)
    {
        int from,to;
        k = 0;
        scanf("%s",ch);
        ID(ch);//big boss是0号
        for(int i = 1; i < n; ++i)
        {
            scanf("%s%s",ch,fa);
            from = ID(ch);
            to = ID(fa);
            g[to].push_back(from);
        }
        //printf("%d\n",g[0].size());
        memset(d,-1,sizeof(d));
        dp(0,0);
        dp(0,1);
        if(d[0][0] > d[0][1])
        {
            printf("%d ",d[0][0]);
            if(f[0][0]) puts("Yes");
            else puts("No");
        }
        else if(d[0][0] < d[0][1])
        {
            printf("%d ",d[0][1]);
            if(f[0][1]) puts("Yes");
            else puts("No");
        }
        else
        {
            printf("%d ",d[0][1]);
            puts("No");
        }
        for(int i = 0; i < n; ++i) g[i].clear();

    }
}

 

posted @ 2015-09-02 15:28  Norlan  阅读(391)  评论(0编辑  收藏  举报