CF600F Edge coloring of bipartite graph 题解
猜测
点染色判断二分图的方法想必大家都有所耳闻,那么边染色呢?
给出一个二分图,求最小边染色。
当看到最小边染色这几个字时,大胆猜测:
二分图的最小边染色结果等于点的最大度数。
相邻边颜色不同已经为此做下了铺垫:由于一个点的度数记录的是与这个点相连的边数,而这些边都相邻,不能是同一种颜色,所以猜测二分图的最小边染色结果等于点的最大度数。
证明:
设点的最大度数为
显然,
考虑构造一种染色方法:
对于任意一条边
定义
若
即存在一种颜色使得集合
直接用其将
若
说明在集合
找出这条边,设为
将
将
此时
但是
设从
此时,从
由于此图是二分图,所以必定有一条边的两种颜色不冲突。
而其中的
构造完毕。
证毕。
发现链的长度最多为
- 小结论:简单图最小边染色为
k\leq ans \leq k+1 。
代码
代码中包含讲解:
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
inline void print(int x){
if(x<0)putchar('-'),x=-x;
if(x>9)print(x/10);
putchar(x%10^48);
}
const int MAXN=2e3+5;
const int MAXM=1e5+5;
int a,b,m,u[MAXM],v[MAXM],in[MAXN];
int ans,color1,color2,color[MAXN][MAXN];
//color[i][j]=k表示(i,k)这条边的颜色为j
int main(){
a=read(),b=read(),m=read();
for(int i=1;i<=m;++i){
u[i]=read(),v[i]=read();
v[i]+=a;
//将v[i]的大小计入总图中
in[u[i]]++,in[v[i]]++;
//统计度数
}
for(int i=1;i<=a+b;++i){
ans=max(ans,in[i]);
//寻找最大度数
}
for(int i=1;i<=m;++i){
color1=1,color2=1;
while(color[u[i]][color1])++color1;
while(color[v[i]][color2])++color2;
//寻找到mex(C1),mex(C2)
color[u[i]][color1]=v[i];
color[v[i]][color2]=u[i];
//标记
if(color1==color2)continue;
//若颜色不冲突,则直接染色
for(int tmp=color2,w=v[i];w;w=color[w][tmp],tmp^=color1^color2){
swap(color[w][color1],color[w][color2]);
}
//通过异或实现color1和color2的交替染色
}
print(ans),puts("");
for(int i=1;i<=m;++i){
for(int j=1;j<=ans;++j){
if(color[u[i]][j]==v[i]){
print(j),printf(" ");
}
}
}
//匹配输出
return 0;
}
如果你觉得这篇题解讲得还算好的话,可以点个赞支持一下呀,谢谢大家!