CF 633 div1 1338 B. Edge Weight Assignment 构造

LINK: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;
}
posted @ 2020-04-15 20:09  chdy  阅读(184)  评论(0编辑  收藏  举报