POJ 3342 Party at Hali-Bula

Party at Hali-Bula

好久沒有寫解題報告了,這次把上個月做的一些題都寫寫,上個月做了不少的樹形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 ;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章