ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF1240F Football

2020-07-10 14:34:53  阅读:355  来源: 互联网

标签:CF1240F int 染色 Football tot add id define


题面

英文题面

题意:有一张\(n\)点\(m\)边的无向图,有\(k\)种颜色,你需要对每条边染上这\(k\)种颜色的其中一种,也可以不染色。需要满足以下限制。

设\(s_{i,j}\)表示以\(i\)为一端的边有多少个被染了颜色\(j\)。则\(\forall i,max_{j=1}^k s_{i,j}-min_{j=1}^k s_{i,j} \leq 2\)。

每个点有一个权值\(w_i\),每染一条\((i,j)\)的边,就会产生\(w_i +w_j\)的贡献。请输出一种合法染色方案,使得总贡献最大。

\(n \leq 100,m,k \leq 1000\)。

题解:首先,一定存在一种染色方案,使得所有边都被染色。

我们先考虑一下\(k=2\)的情况如何进行染色。考虑到如果所有节点的度数都为偶数,我们一定能够找到一条遍历了所有边的回路。因此我们可以试图将原图转化。

  • 新建一个虚拟节点“0”;
  • 对于存在度数为奇数的点的连通块,我们让所有这些点与0号节点连边;
  • 对于所有点度数都为偶数的连通块,我们任意指定一个点,与0号节点连两条边。

不难发现这样构造之后,所有点的度数都是偶数。这样,我们就DFS找到这条回路,然后按照\(1212\cdots 12\)对边进行染色即可,最后将0号节点和与其有关的边删掉就行了。不难发现这样操作过后,每个点的\(max-min \leq 1\)。

那么对于\(k>2\)的情况,我们可以先将所有边随机染色,然后不断判断每个点的染色情况是否合法。如果有不合法的,就拿出\(max\)和\(min\)对应的这两种颜色,将图中这些边重新染色即可。可以发现这样操作并不会使任何点的\(max-min\)增加。

(下面引用了大神Um_nik的复杂度证明。)

我们设$P(Coloring)= \sum_i \sum_j s_{i,j}^2 \((\)s_{i,j}$的定义见题目描述)。那么有\(0 \leq P(Coloring) \leq 2nm\)。每做一次操作,\(P(Coloring)\)是严格递减的。因此,操作次数的上界是\(2nm\)次,一次操作的复杂度是\(O(n+m)\),那么总复杂度就是\(O(nm(n+m))\)。

但由于我们对所有边进行了随机化染色,因此,对于一个度数为\(d\)的节点,它对\(P\)的期望贡献是\(d+d(d-1)/k=d^2/k+d(1-\frac{1}{k})\),可以近似看作是\(d^2/k\)。因此,期望操作次数是\(O(m)\)级别的,可以通过本题。

代码:

#include<bits/stdc++.h>
using namespace std;
#define re register int
#define F(x,y,z) for(re x=y;x<=z;x++)
#define FOR(x,y,z) for(re x=y;x>=z;x--)
typedef long long ll;
#define I inline void
#define IN inline int
#define C(x,y) memset(x,y,sizeof(x))
#define STS system("pause")
template<class D>I read(D &res){
	res=0;register D g=1;register char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-')g=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		res=(res<<3)+(res<<1)+(ch^48);
		ch=getchar();
	}
	res*=g;
}
const int INF=1e9+7;
typedef pair<int,int>pii;
vector<pii>e[110];
struct E{
	int to,nt,id;
}t[20200];
#define T t[k].to
int n,m,k,x,clr,tot,v[110],vis[1010],head[110],du[110],a[1010],b[1010],c[1010],cnt[1010];
stack<int>s;
I add(int x,int y,int id){
	t[++tot].to=y;t[tot].nt=head[x];head[x]=tot;t[tot].id=id;du[y]++;
}
I D_1(int x){
	v[x]=1;
	for(re k=head[x];k!=-1;k=t[k].nt){
		if(!v[T])D_1(T);
	}
}
I D_2(int x,int id){
	for(re &k=head[x];k!=-1;k=t[k].nt){
		if(!vis[k>>1]){
			vis[k>>1]=1;
			D_2(T,t[k].id);
		}
	}
	s.emplace(id);
}
I recolor(int A,int B){
	C(head,-1);tot=-1;C(v,0);C(du,0);
	F(i,1,m)if(c[i]==A||c[i]==B)add(a[i],b[i],i),add(b[i],a[i],i);
	F(i,1,n){
		if(du[i]&1){
			add(i,0,0);add(0,i,0);
			if(!v[i])D_1(i);
		}
	}
	F(i,1,n){
		if(v[i]||(du[i]&1))continue;
		D_1(i);
		add(0,i,0);add(i,0,0);
		add(0,i,0);add(i,0,0);
	}
	F(i,0,tot>>1)vis[i]=0;
	D_2(0,0);clr=0;
	while(!s.empty())c[s.top()]=(clr?A:B),s.pop(),clr^=1;
}
int main(){
	srand((unsigned)time(0)+19260817);
	read(n);read(m);read(k);
	F(i,1,n)read(x);
	F(i,1,m)read(a[i]),read(b[i]),e[a[i]].emplace_back(make_pair(b[i],i)),e[b[i]].emplace_back(make_pair(a[i],i)),c[i]=rand()%k+1;
	while(1){
//		cout<<"!";
		re sn=1,mx,mn,px,pn;
		F(i,1,n){
			mx=0;px=pn=1;mn=INF;F(j,1,k)cnt[j]=0;
			for(auto d:e[i])cnt[c[d.second]]++;
			F(j,1,k){
				if(cnt[j]>mx)mx=cnt[j],px=j;
				if(cnt[j]<mn)mn=cnt[j],pn=j;
			}
			if(mx-mn>2)recolor(px,pn),sn=0;
		}
		if(sn)break;
	}
	F(i,1,m)printf("%d\n",c[i]);
	return 0;
}

标签:CF1240F,int,染色,Football,tot,add,id,define
来源: https://www.cnblogs.com/Purple-wzy/p/13279053.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有