树形DP水题。判断取法是否唯一,dp的时候记录一下每个状态从下面的子节点推导过来的时候是否唯一即可。
#include<cstdio> #include<cstring> #include<cmath> #include<ctime> #include<map> #include<vector> #include<string> #include<algorithm> #include<iostream> using namespace std; const int maxn=200+10; map<string,int>v; vector<int>tree[maxn]; int n,id; int dp[maxn][5],flag[maxn][5]; string s; bool vis[maxn]; void init() { id=0; v.clear(); memset(dp,0,sizeof dp); memset(flag,0,sizeof flag); memset(vis,0,sizeof vis); for(int i=0;i<=n;i++) tree[i].clear(); } void read() { cin>>s; if(!v[s]) v[s]=++id; for(int i=1;i<=n-1;i++) { int a,b; cin>>s; if(v[s]==0) v[s]=++id; a=v[s]; cin>>s; if(v[s]==0) v[s]=++id; b=v[s]; tree[a].push_back(b); tree[b].push_back(a); } } void dfs(int now) { bool fail=1; for(int i=0;i<tree[now].size();i++) if(!vis[tree[now][i]]) fail=0; if(fail) { dp[now][1]=1; dp[now][0]=0; return; } int sum1=1,sum2=0; for(int i=0;i<tree[now].size();i++) { int id=tree[now][i]; if(vis[id]) continue; vis[id]=1; dfs(id); sum1=sum1+dp[id][0]; if(flag[id][0]==1) flag[now][1]=1; sum2=sum2+max(dp[id][1],dp[id][0]); if(dp[id][1]==dp[id][0]) flag[now][0]=1; else if(dp[id][1]>dp[id][0]){if(flag[id][1]) flag[now][0]=1;} else {if(flag[id][0]) flag[now][0]=1;} } dp[now][1]=sum1; dp[now][0]=sum2; } void work() { vis[1]=1; dfs(1); printf("%d ",max(dp[1][0],dp[1][1])); bool ans=0; if(dp[1][0]>dp[1][1]) {if(flag[1][0]) ans=1;} else if(dp[1][0]<dp[1][1]) {if(flag[1][1]) ans=1;} else ans=1; if(ans) printf("No\n"); else printf("Yes\n"); } int main() { while(~scanf("%d",&n)) { if(!n) break; init(); read(); work(); } return 0; }
时间: 2024-11-14 23:27:22