好久沒有寫解題報告了,這次把上個月做的一些題都寫寫,上個月做了不少的樹形DP,先從這個比較簡單的入手。
這個題目與hdu 1520 Anniversary party那道很裸的樹形DP差不多,只不過這道題不僅要求出最多的人,還要判斷是不是唯一。主要是如何判斷人數是不是唯一的。出現多解的情況可能有如下兩種,如果對於根節點而言,選與不選的解是相同的,則說明這樣肯定會是多解,另一種情況就是由於兒子節點的多解導致父親節點的多解。所以我們可以用一個二維數組來標記某個節點由兒子節點更新到父親節點的時候是不是有多解。對於選擇父親節點,那麼可能導致的情況就是兒子節點不選的時候有多解,那麼需要將這種多解的標記更新到父親節點。對於不選擇父親節點,那麼就有可能是兒子節點選與不選解都是相同的,或者兒子節點較大的那種選擇有多解標記,此時我們標記父親節點。具體代碼如下:
/*
*author : csuchenan
*PROG : POJ3342
*Algorithm : TreeDP ,注意判重複的情況,
*這裏如果某個點出現重複的情況那麼就更新給父親節點
*對於根節點只需要特判一下
*10792694 csuchenan 3342 Accepted 212K 0MS C++ 1955B 2012-09-11 11:12:53
*/
#include <cstdio>
#include <cstring>
#include <vector>
using std::vector ;
#define maxn 205
vector<int> G[maxn] ;
char name[205][105] ;
int dp[maxn][2] ;
bool special[maxn][2] ;
int n ;
int len ;
int insert(char * str){
strcpy(name[len] , str ) ;
len ++ ;
return len - 1 ;
}
int find(char *str){
int i(0) ;
while(i < len && strcmp(str , name[i]) != 0 )
i ++ ;
if(i == len )
return -1 ;
return i ;
}
void init(){
for(int i = 0 ; i <= n ; i ++){
G[i].clear() ;
}
memset(name , 0 , sizeof(name)) ;
memset(dp , 0 , sizeof(dp)) ;
memset(special , 0x1 , sizeof(special)) ;
len = 0 ;
}
inline int max(int x , int y){
return x > y ? x : y ;
}
void dfs(int v){
for(vector<int> :: size_type i = 0 ; i != G[v].size() ; i ++){
int u = G[v][i] ;
dfs(u ) ;
dp[v][0] += max(dp[u][1] , dp[u][0]) ;
dp[v][1] += dp[u][0] ;
if(dp[u][1] == dp[u][0]){
special[v][0] = 0 ;
}
else if(dp[u][0] > dp[u][1] && special[v][0]){
special[v][0] = special[u][0] ;
}
else if(dp[u][0]< dp[u][1] && special[v][0]){
special[v][0] = special[u][1] ;
}
if(special[v][1]){
special[v][1] = special[u][0] ;
}
}
dp[v][1] ++ ;
}
int main(){
char str[105] ;
//freopen("POJ3342.txt" , "r" , stdin) ;
while(scanf("%d" , &n) , n){
init() ;
scanf("%s" , str) ;
insert(str) ;
int p , q ;
for(int i = 1 ; i < n ; i ++){
scanf("%s" , str) ;
if( (p=find(str)) == -1 )
p = insert(str) ;
scanf("%s" , str) ;
if( (q=find(str)) == -1 )
q = insert(str) ;
//G[p].push_back(q) ;
G[q].push_back(p) ;
}
dfs(0) ;
int ans = max(dp[0][0] , dp[0][1]) ;
printf("%d " , ans ) ;
if(dp[0][0] == dp[0][1] )
puts("No") ;
else if( ((dp[0][0] > dp[0][1]) && !special[0][0]) ||
((dp[0][1] > dp[0][0]) && !special[0][1] ) )
puts("No") ;
else
puts("Yes") ;
}
return 0 ;
}