CF 633 div1 1338 B. Edge Weight Assignment 构造
这场当时没打 看到这个B题吓到我了 还好当时没打。
想了20min才知道怎么做 而且还不能证明.
首先考虑求最小。
可以发现 如果任意两个叶子节点之间的距离都是偶数 那么显然 答案为1.
可以发现 如果有两个叶子之间的距离为奇数 那么答案至少为3.
考虑画多张图 可以发现不管怎么做 答案最多为3.
尝试证明:对于两个点之间的距离是奇数时 每三段我们认为是0 最后一定剩下两端 填一样的数字即可。
可以发现这样构造可行。(画图证明法更好一点.
考虑求最大。
容易猜想是不是树的直径 然后被样例3打脸.
可以发现如果有连个叶子节点之间的距离为2,那么 这两条边必然相同。
考虑是否还存在这样的情况 可以发现不存在了。
接着对着直径先构造一波 考虑除掉上述情况的其他链 可以发现 可以 使用不同的颜色染且最后还是正确的。
猜想 除掉上述情况 剩下的所有边都有代价1.
经过不断的画图+构造 可以发现这是正确的。
想出来这两个结论的时候 我也觉得挺不可思议的 但是这确实是正确的 可以构造出来。
const int MAXN=100010;
int n,len,flag;
int f[MAXN][2],ru[MAXN];
int lin[MAXN],ver[MAXN<<1],nex[MAXN<<1];
inline void add(int x,int y)
{
ver[++len]=y;
nex[len]=lin[x];
lin[x]=len;
}
inline void dfs(int x,int fa)
{
f[x][0]=f[x][1]=-1;
if(ru[x]==1)f[x][0]=1;
go(x)
{
if(tn==fa)continue;
dfs(tn,x);
if(f[tn][0]!=-1&&f[x][0]!=-1)flag=1;
if(f[tn][1]!=-1&&f[x][1]!=-1)flag=1;
if(f[tn][0]!=-1)f[x][1]=1;
if(f[tn][1]!=-1)f[x][0]=1;
}
}
int main()
{
//freopen("1.in","r",stdin);
get(n);
rep(2,n,i)
{
int get(x);int get(y);
add(x,y);add(y,x);
++ru[x];++ru[y];
}
dfs(1,0);
if(flag)printf("%d ",3);
else printf("%d ",1);
int cnt=n-1;
rep(1,n,j)
{
int w=0;
go(j)if(ru[tn]==1)++w;
if(w)cnt=cnt-w+1;
}
printf("%d\n",cnt);
return 0;
}