题意跟hdu1520一样,给定一棵树,要求选出若干个点,但如果选择了父节点跟儿子节点不可以同时选。。求可以选出的节点数的最大值,同时,判断该选法是否唯一;
分析:前半部分很容易实现,普通的树形dp,关键是如何判断是否唯一。
我们用flag[N][2]来记录每一个节点的情况
flag[i][j]为真,表示唯一
则可以这样判断
对于叶子结点, flag[k][0] = flag[k][1] = 1.
对于非叶子结点,
对于i的任一儿子j,若(dp[j][0] > dp[j][1] 且 flag[j][0] == 0) 或 (dp[j][0] < dp[j][1] 且 flag[j][1] == 0) 或 (dp[j][0] == dp[j][1]),则flag[i][0] = 0
对于i的任一儿子j有flag[j][0] = 0, 则flag[i][1] = 0
View Code
#include#include #include #include using namespace std; const int N =210; int n,num,dp[N][2]; vector g[N]; bool flag[N][2]; typedef struct node { int cnt; struct node *next[52]; }*tree,Trie; tree root; inline int GetNum(char *t){ tree p = root,newnode; for(int i = 0;i < strlen(t); ++i){ int u = t[i] - 'a'; if(u<0) u=t[i]-'A'+26; if(p->next[u]==NULL) { newnode=(tree)malloc(sizeof(Trie)); newnode->cnt=-1; for(int j=0;j<52;j++) newnode->next[j]=NULL; p->next[u]=newnode; p=newnode; } else p = p->next[u]; } if(p->cnt == -1) //该节点未出现过 p->cnt = num ++; return p->cnt; } void init() { root=(tree)malloc(sizeof(Trie)); root->cnt=-1; for(int j=0;j<52;j++) root->next[j]=NULL; num=1; for(int i=0;i<=n;i++) g[i].clear(); memset(dp,0,sizeof(dp)); memset(flag,true,sizeof(flag)); } void dfs(int u) { int size=g[u].size(); for(int i=0;i dp[v][1] && !flag[v][0])|| (dp[v][0] dp[s][1] && flag[s][0]) puts("Yes"); else if(dp[s][1]>dp[s][0] && flag[s][1]) puts("Yes"); else puts("No"); } return 0; }