天天看点

CodeForces 1141G 构造

当时因为__int128不能用,然后E题爆long long 花了好长时间,其实不用二分。。。直接算出来。

其次这场的C题因为无解数据可能导致数组越界,而且爆int,所以被hack了= =

还是得多打div3练习思维严密性,快速想到坑点。

然后这个G题半个小时硬是冇得想法,二分答案以后不知道怎么办,因为想到一个点把他的边全部染色以后,枚举到其他点的时候有一些边已经被染过色了,于是就不知道怎么办了,感觉得每个点开个set,然而又要考虑到这个点要是超出r,要给那些重复颜色的点安排哪些颜色的问题,不知道怎么做了。

看了题解。。。原来直接按照dfs顺序,由于这是一棵树,所以和父节点只有一条边重复,那么这样就直接枚举下去就行了,跳过父边的颜色一次,第二次就算他重复了。

那么这样可以直接算出r了,当du[i]>r的个数恰好小于等于r时就行。

2500分的题还是做不来,菜哭.jpg

#include<bits/stdc++.h>
#define maxl 200010
using namespace std;

int n,k,cnt,r;
int ans[maxl],ehead[maxl],du[maxl],num[maxl];
struct ed
{
	int nxt,to,ind;
}e[maxl<<1];

inline void add(int u,int v,int i)
{
	e[++cnt].to=v;e[cnt].nxt=ehead[u];ehead[u]=cnt;
	e[cnt].ind=i;
}

inline void prework()
{
	scanf("%d%d",&n,&k);
	int u,v;
	for(int i=1;i<=n-1;i++)
	{
		scanf("%d%d",&u,&v);
		add(u,v,i);add(v,u,i);
		du[u]++;du[v]++;
	}
	for(int i=1;i<=n;i++)
		num[du[i]]++;
	int sum=0;
	for(int i=n;i>=1;i--)
	{
		sum+=num[i];
		if(sum>k)
		{
			r=i;
			return;
		}
	}
}

inline void dfs(int u,int fa,int fcol)
{
	int v;int col=1;
	for(int i=ehead[u];i;i=e[i].nxt)
	{
		v=e[i].to;
		if(v==fa) continue;
		if(col==fcol)
		{
			col=col+1;
			if(col>r) col=1;
			fcol=0;
		}
		ans[e[i].ind]=col;
		dfs(v,u,col);
		col=col+1;
		if(col>r) col=1;
	}
}

inline void mainwork()
{
	dfs(1,0,0);
}

inline void print()
{
	printf("%d\n",r);
	for(int i=1;i<=n-1;i++)
		printf("%d ",ans[i]);
}

int main()
{
	prework();
	mainwork();
	print();
	return 0;
}