题意:给定一棵树,给边赋任意值,要求所以叶子节点间的路径权值异或和为0 ,求出不同值个数的最大值和最小值
对于最大值,考虑DP,以不为叶结点的结点i作为根,因此他的儿子结点可以分成两种情况,一种仍是叶子结点ui,另一种是分支
节点vi,假设mx[i]表示以i为根节点的子树得到的最大值,则显然所有叶子结点连到i的边的权值需要相同,
其次其他的子树则可以直接相加 ;
对于最小值,可以将整棵树放平,看作一条长链,简化成下图所示,因此最小值只可能为1或者3,只要某条路径出现奇数长则最
小值为3,否则为1;
#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int N = 1e5+10;
int n,mn,mx[N];
int in[N];
vector<int> e[N];
inline void adde(int x,int y){
e[x].pb(y);
e[y].pb(x);
}
void dfs(int x,int fa){
bool first=1;
for(int i=0;i<(int)e[x].size();i++){
int y=e[x][i];
if(y != fa){
dfs(y,x);
if(in[y] == 1){
if(first){
mx[x]++;
}
first=0;
}
else {
mx[x] += mx[y]+1;
}
}
}
}
int minn=1;
void dfs_1(int o,int fa,int deep){
if(in[o]==1&&fa!=0){
if(deep%2)minn=3;
return ;
}
for(int i=0;i<(int)e[o].size();i++){
int y=e[o][i];
if(y != fa)
dfs_1(y,o,deep+1);
}
}
int main(){
scanf("%d", &n);
for(int i=1,x,y;i<n;i++){
scanf("%d %d", &x, &y);
adde(x,y);
in[x]++; in[y]++;
}
for(int i=1;i<=n;i++)
if(in[i]==1){
dfs_1(i,0,0);
break;
}
for(int i=1;i<=n;i++){
if(in[i] != 1){
dfs(i,-1);
printf("%d %d\n",minn,mx[i]);
break;
}
}
return 0;
}