Description
给定一棵有根树,甲乙轮流操作,每次每人选择一条边走,从根走到一个叶子,甲希望最后得到的叶子结点的权值尽可能大,乙希望最后得到的叶子结点的权值尽可能小,两人都采取最优策略。现在需要给每个叶子节点分配权值,权值是 (1 sim m) 的全排列。问让甲分配权值则最后取得的最大权值是多少,让乙分配权值则最后取得的最小权值是多少。
Solution
树形 dp,设 (f[i]) 表示 (i) 点子树内能达到的最小排名,(h[i]) 表示最大排名,则有
[f[i]=min_{i o j} h[j], h[i]=sum_{i o j} f[j]
]
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1000005;
vector <int> g[N];
int n,m,t1,t2,f[N],h[N],vis[N];
void dfs(int p)
{
vis[p]=1;
f[p]=n+1;
int fg=0;
for(int q:g[p])
{
if(vis[q]==0)
{
fg=1;
dfs(q);
f[p]=min(f[p],h[q]);
h[p]+=f[q];
}
}
if(fg==0)
{
f[p]=h[p]=1;
++m;
}
}
signed main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<n;i++)
{
cin>>t1>>t2;
g[t1].push_back(t2);
g[t2].push_back(t1);
}
dfs(1);
cout<<m-f[1]+1<<" "<<h[1]<<endl;
}