poj3342树形dp+深度搜索并确定唯一性

来源:互联网 发布:2017电视盒子 知乎 编辑:程序博客网 时间:2024/04/28 16:44
//树形dp入门题目//使得每2个人之间不能有直接的上下级的关系,求最多能选多少个人出来,并且求出获得最大人数的选人方案是否唯一//唯一性通过状态数组递归确定//dp[i][0] = ∑max(dp[j][0], dp[j][1]) (j是i的儿子)//dp[i][1] = 1 + ∑dp[j][0] (j是i的儿子) 
//268K32MS#include <iostream>#include <map>#include <string>#include <vector>using namespace std;#define  MAX_N 206static int n;static int dp[MAX_N][2];//表示第i个节点选取或者不选取的时候最大的总数static int dup[MAX_N][2];//表示当前结点的状态是否唯一//建立树结构struct  edge{edge(int f,int to):u(f),next(to){}int u;//起点int next;//终点};vector<edge> Tree[MAX_N];//表示整棵树static void initTree(){for (int i=0;i<MAX_N;++i){  Tree[i].clear();  dup[i][0] = dup[i][1] = 1;}}//添加x索引的父节点是ystatic void addNode(int x,int y){vector<edge>&vec = Tree[y];vec.push_back(edge(y,x));}static void DFS(int u){if (Tree[u].size()==0)//叶子结点{dp[u][1] = 1;dp[u][0] = 0;dup[u][1] = 1;dup[u][0] = 1;return;}for (int i=0;i<Tree[u].size();++i)//遍历所有边{int t = Tree[u][i].next;DFS(t);dp[u][0] +=max(dp[t][0],dp[t][1]);dp[u][1] +=dp[t][0];if (dup[t][0]==0) dup[u][1] = 0;//若不取孩子不唯一那么当前取根显然不唯一//对于不取根的情况if (dp[t][0]>dp[t][1]&&dup[t][0]==0) dup[u][0] = 0;else if (dp[t][0]<dp[t][1]&&dup[t][1]==0) dup[u][0] = 0;else if (dp[t][0]==dp[t][1]) dup[u][0] = 0;}dp[u][1]+=1;//只加一次}int main(){string str,pstr;while(cin>>n&&n){map<string,int> vstr;map<int,string>par;memset(dp,0,sizeof(dp));initTree();cin>>str;vstr[str] = 0;for (int i=1;i<n;++i){ cin>>str>>pstr; vstr[str] = i; par[i] = pstr;}//加入结点for (int i=1;i<n;++i){string p = par[i];addNode(i,vstr[p]);}DFS(0);char ret[12];if (dp[0][0]>dp[0][1]){if (dup[0][0]==1) strcpy(ret,"Yes");else strcpy(ret,"No");printf("%d %s\n",dp[0][0],ret);}else if (dp[0][0]<dp[0][1]){if (dup[0][1]==1)  strcpy(ret,"Yes");else strcpy(ret,"No");printf("%d %s\n",dp[0][1],ret);}elseprintf("%d No\n",dp[0][1]);}return 0;}

0 0