30分的暴力,当
n<=10
时,还是很好做的辣、
就是给每个叶子节点固定权值。然后树形
dp
就可以了,因为一个点被先手或是被后手取是确定的,就很好写了。
n<=200000
时肯定就不能枚举了。。
既然无法确定叶节点权值,那么转化一下,
dp
不求具体值是多少,改为求第几大。
fx
表示当前点取最大的是第几大,
gx
表示当前点取最小的是第几小。
显然
fx
应该用儿子节点的
g
转移。
既然
但是
g
不能是
。。总感觉怪怪的。
【代码】
#include <cstdio>
#include <iostream>
#include <queue>
#include <cmath>
#include <algorithm>
#define N 200005
#define INF 0x7fffffff
using namespace std;
typedef pair<int,int> pa;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
int n,cnt,Num;
int b[N],p[N],nextedge[N];
int g[N],f[N];
void Add(int x,int y) {
cnt++;
b[cnt]=y;
nextedge[cnt]=p[x];
p[x]=cnt;
}
void Dfs(int x) {
if(!p[x]) {
f[x]=g[x]=1;Num++;
return;
}
f[x]=INF;
for(int i=p[x];i;i=nextedge[i])
{
int v=b[i];
Dfs(v);
f[x]=min(f[x],g[v]);
g[x]+=f[v];
}
}
void Work()
{
for(int i=1;i<n;i++){
static int x,y;
x=read(),y=read();
Add(x,y);
}
Dfs(1);
printf("%d %d\n",Num-f[1]+1,g[1]);
}
int main()
{
n=read();
Work();
return 0;
}