题目地址点击打开链接;
开始以为是各种dfs爆搜yy中。。。;
不想完全看题解,搞了很久,看了一眼后缀,据说是树形dp;
然后顿悟开始修改;随他去吧;
用一个二维dp【a】【b】 来更新最大值,a表示这个节点的编号,b有两个值,0,1表示这个点取与不取;
用一个vector来建树;从根节点开始,也就是big boss,向他的员工出发dfs,每个点可以取,也可以不取,
取:该点的所有子结点都不可取;
不取:该点的所有子节点中寻找取与不取的最大值来更新;
当到达叶子时,叶子一定是取的(max)并且dp【a】【1】值为1,因为只有这一个人;
然后就得到最大值了;
差一点gg的是,他要求你判断max的方案是否唯一,我傻,没办法,于是再来一个dfs来开始判断
取:从子节点不取中判断;
不取: 如果子节点的取和不取的值相同的话,那说明一点方案不唯一,(因为当初取的时候就是存的取和不取中的最大值,如果两者相等,则说明重复)
#include <iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cstdio>
#include<map>
#include<vector>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=200+5;
map<string,int>mp;
int n;
int vis[maxn];
vector<int> eg[maxn];
int flag;
int nn;
int ans;
int dp[maxn][3];
void dfs(int a,int ok)
{
if(eg[a].size()==0&&ok)
{
dp[a][1]=1;
dp[a][0]=0;
}
if(vis[a])
return;
if(ok)
{
dp[a][1]=1;
for(int i=0;i<eg[a].size();i++)
{ vis[a]=1;
dfs(eg[a][i],0);
dp[a][1]+=dp[eg[a][i]][0];
}
}
dp[a][0]=0;
for(int i=0;i<eg[a].size();i++)
{
dfs(eg[a][i],1);
dp[a][0]+=max(dp[eg[a][i]][1],dp[eg[a][i]][0]);
}
if(dp[a][0]==dp[a][1])
flag=1;
}
int oj(int a,int ok)
{
if(ok)
{
for(int i=0;i<eg[a].size();i++)
if(oj(eg[a][i],0))
return 1;
}
else
{
for(int i=0;i<eg[a].size();i++)
{
if(dp[eg[a][i]][0]==dp[eg[a][i]][1])
return 1;
}
}
return 0;
}
int main()
{
string a,b;
while(cin>>n&&n)
{
cin>>a;
int num=1;
mp.clear();
for(int i=0;i<=n;i++)
eg[i].clear();
mp[a]=num;
for(int i=0;i<n-1;i++)
{
cin>>a>>b;
if(!mp[a])
{
num++;
mp[a]=num;
}
if(!mp[b])
{
num++;
mp[b]=num;
}
eg[mp[b]].push_back(mp[a]);
}
nn=0;
ans=0;
flag=0;
memset(vis,0,sizeof(vis));
memset(dp,0,sizeof(dp));
dfs(1,1);
ans=max(dp[1][0],dp[1][1]);
if(dp[1][0]==dp[1][1])
flag=1;
else
{
if(dp[1][0]>dp[1][1])
flag=oj(1,0);
else
flag=oj(1,1);
}
cout<<ans<<" ";
if(flag)
cout<<"No"<<endl;
else
cout<<"Yes"<<endl;
}
return 0;
}
唉,太菜了 了 了了了了了了了了了,继续努力啊!!!
不过还好,以后一定要坚持,觉得如果自己不看题解也可以做出来的题那么,你就不要看题解!