CF#633 D. Edge Weight Assignment
D. Edge Weight Assignment
题意
给出一个n个节点的树,现在要为边赋权值,使得任意两个叶子节点之间的路径权值异或和为0,问最多,最少有多少个不同的权值。
题解
最大值:
两个叶子节点x,y,如果他们的父亲都是z,那么[x,z],[y,z]的权值必须相同。
其他边可以保证任意两个边的权值都不相同。
最小值:
如果任意两个叶子节点的路径长度为偶数,给所有边赋一个正值就可以。
如果存在奇数:最少需要三个值。
代码
#include<bits/stdc++.h>
#define pb push_back
using namespace std;
typedef long long ll;
const int N=1e6+10;
vector<int>vec[N];
int in[N],vis[N];
int maxn;
void dfs(int u,int pre,int col)
{
vis[u]=col;
int num=0;
for(int v:vec[u])
{
if(v==pre)
continue;
dfs(v,u,col^1);
if(in[v]==1) num++;
}
if(num) maxn-=(num-1);
}
int main()
{
int n;
scanf("%d",&n);
maxn=n-1;
for(int i=1; i<n; i++)
{
int u,v;
scanf("%d%d",&u,&v);
vec[u].pb(v);
vec[v].pb(u);
in[u]++,in[v]++;
}
for(int i=1;i<=n;i++)
{
if(in[i]!=1)
{
dfs(i,0,0);
break;
}
}
int flag=0,num=0;
for(int i=1;i<=n;i++)
{
if(in[i]==1)
{
num++;
flag+=vis[i];
}
}
if(flag!=0&&flag!=num)
{
if(n==2) printf("1 ");
else printf("3 ");
}
else printf("1 ");
printf("%d\n",maxn);
return 0;
}