CF1240F Football

题目传送门

分析:
先转化一下模型,把队伍看作点,两个队伍比赛看作边,给边\(K\)染色,假设以点\(i\)为端点,颜色最大的值为\(mx_i\),最小为\(mn_i\)
我们需要找到染色方案使得对于每一个点\(i\)\(mx_i-mn_i\leq 2\)
不知道所有的比赛是否都可以举行,我们先尝试看看能不能每条边都染色
先思考\(K=2\)的情况吧,我们新建节点0,如果一个点度数为奇数,将这个点与0连边
接下来这个图的每个点度数都为偶数了
接下来在这个图上胡乱dfs,保证所有边只经过一次,把这些边按顺序加入队列
把这些边按加入顺序的奇偶性染色,再删去0和与0相连的边
可以保证每个点\(mx_i-mn_i\leq 1\)
非常巧妙的构造,可以联系一下欧拉回路证明其正确性
访问一个点再离开,入边和出边在队列里相邻,必定不同色,可以被抵消二保证\(mx_i-mn_i=0\)
删除0点后度数为奇数的点最多被删一条边,也能保证\(mx_i-mn_i=1\)
对于\(K>2\)的情况,我们先随机染色,然后找到某个不合法的点出现最多的颜色\(C_1\),和最少的颜色\(C_2\)
\(C_1,C_2\)\(K=2\)的方法染色,这样我们会让\(mx_i-mn_i\)不断缩小,最后求得答案
这样可以求得让每一条边都染色的合法方案,即每一场比赛都能举行
(不会证明QAQ,感性理解感觉很对2333)
最坏情况复杂度\(O(nm^2)\),由于随机跑不满,可以通过(
(可能是我的写太丑了常数巨大,随机种子多试了几次才过的

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#include<queue>
#include<bitset>
#include<map>
#include<set>

#define maxn 1105
#define MOD 1000000007

using namespace std;

inline int getint()
{
	int num=0,flag=1;char c;
	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
	return num*flag;
}

int n,m,K;
struct node{
	int u,v,col;
}E[maxn];
int D[105][maxn],d[105];
int C1=1,C2=1;
vector<int>G[105],Id[105];
int vis[maxn],stk[maxn],tp;

inline bool check()
{
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=K;j++)
		{
			if(D[i][j]>D[i][C1])C1=j;
			if(D[i][j]<D[i][C2])C2=j;
		}
		if(D[i][C1]-D[i][C2]>2)return 0;
	}
	return 1;
}

inline void dfs(int u)
{
	for(int i=0;i<G[u].size();i++)if(!vis[Id[u][i]])
	{
		vis[Id[u][i]]=1,stk[++tp]=Id[u][i];
		dfs(G[u][i]);
	}
}

int main()
{
	srand(19260817);
	n=getint(),m=getint(),K=getint();
	for(int i=1;i<=n;i++)getint();
	for(int i=1;i<=m;i++)E[i].u=getint(),E[i].v=getint(),E[i].col=rand()%K+1;
	for(int i=1;i<=m;i++)D[E[i].u][E[i].col]++,D[E[i].v][E[i].col]++;
	while(1)
	{
		if(check())break;
		for(int i=1;i<=m;i++)if(E[i].col==C1||E[i].col==C2)
		{
			G[E[i].u].push_back(E[i].v),G[E[i].v].push_back(E[i].u);
			Id[E[i].u].push_back(i),Id[E[i].v].push_back(i);
			d[E[i].u]++,d[E[i].v]++;
		}
		int num=m;
		for(int i=1;i<=n;i++)if(d[i]&1)
		{
			G[i].push_back(0),G[0].push_back(i);
			Id[i].push_back(++num),Id[0].push_back(num);
		}
		for(int i=0;i<=n;i++)dfs(i);
		for(int i=1;i<=n;i++)D[i][C1]=D[i][C2]=0;
		while(tp)
		{
			if(stk[tp]<=m)E[stk[tp]].col=tp&1?C1:C2,D[E[stk[tp]].u][E[stk[tp]].col]++,D[E[stk[tp]].v][E[stk[tp]].col]++;
			tp--;
		}
		for(int i=0;i<=n;i++)G[i].clear(),Id[i].clear();
		memset(d,0,sizeof d),memset(vis,0,sizeof vis);
	}
	for(int i=1;i<=m;i++)printf("%d\n",E[i].col);
}

posted @ 2020-07-10 19:14  Izayoi_Doyo  阅读(221)  评论(0编辑  收藏  举报