hdu 2412

来源:互联网 发布:城觅 网络异常 编辑:程序博客网 时间:2024/05/21 09:29

一题树形dp,思想难度要大一点,需要头脑清晰的分析。编程实现并不难。首先,得考虑用什么来保存状态。用d[u][k], k = 1,表示选择了u,k = 0时表示不选u。选不选的状态定好之后,接下来判断方案是否唯一。f[u][k] 如果为1,那么方案唯一,否则不唯一。

先实现的时候还需考虑,如果是d[u][1]的情况,那么f[u][k]由d[v][0]来决定。如果是d[u][0]的情况那么要分情况考虑。如果d[v][1] > d[v][0] 那么取决于d[v][1]。如果d[v][1] < d[v][0] 那么取决于d[v][0]。否则直接为0。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<map>#include<vector>#include<string>using namespace std;const int maxn = 200 + 5;map<string, int> id;vector<int> sons[maxn];int d[maxn][2];int f[maxn][2];int cnt = 0;int get_id(string s){    if(!id.count(s))        id[s] = cnt++;    return id[s];}int dp(int u, int k){    d[u][k] = k;    f[u][k] = 1;    for(int i = 0; i < sons[u].size(); i++)    {        int v = sons[u][i];        if(k == 1)        {            d[u][k] += dp(v, 0);            if(!f[v][0]) f[u][k] = 0;        }        else        {            d[u][k] += max(dp(v, 1), dp(v, 0));            if(d[v][1] == d[v][0]) f[u][k] = 0;            else if(d[v][1] > d[v][0] && !d[v][1]) f[u][k] = 0;            else if(d[v][1] < d[v][0] && !d[v][0]) f[u][k] = 0;        }    }    return d[u][k];}int main(){    int n;    while(scanf("%d", &n) == 1 && n)    {        cnt = 0;        id.clear();        for(int i = 0; i <= n; i++)            sons[i].clear();        string boss;        cin>>boss;        get_id(boss);        for(int kase = 1; kase < n; kase++)        {            string e, b;            cin>>e>>b;            sons[get_id(b)].push_back(get_id(e));        }        printf("%d ", max(dp(0, 0), dp(0, 1)));        bool uniq = false;        if(d[0][0] > d[0][1] && f[0][0]) uniq = true;        if(d[0][0] < d[0][1] && f[0][1]) uniq = true;        if(uniq) printf("Yes\n");        else printf("No\n");    }    return 0;}