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);
}