题目链接:K-Color_2022图论班第一章图匹配例题与习题 (nowcoder.com)
今天学了一下二分图,做到了这一道题,觉得还是很有意思的
题目大意:
给一个没有重边的二分图, 要求给边染色. 有公共点的边不能同色. 问最少用多少种颜色, 并任意构造一组方案.
做法:匈牙利算法的变形,首先使用的颜色数量是所有点度数的最大值, 每一次都按照当前所有节点的度数由大到小排序,之后将所有没被染色的边放入要进行匈牙利算法的边集中,进行匈牙利算法,注意的是由于每一轮染色,每一个点最多只能染色一条边,所以在进行配对的时候,需要互相配对以保证每一个点在本轮最多只被染色一条边。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int N=1e3+10,M=2e3+10;
int n,m;
vector<int> ve[N];
struct node {
int x,y;
}e[M];
int du[N];
int link[N];
int vis[N];
int timecnt=0;
int dfs(int x) {
for(auto i:ve[x]) {
if(vis[i]!=timecnt) {
vis[i]=timecnt;
if(!link[i]||dfs(link[i])) {
link[i]=x;
link[x]=i;
return 1;
}
}
}
return 0;
}
int col[N][N];
int id[N];
bool cmp(int a,int b) {
return du[a]>du[b];
}
int main() {
int ans=0;
cin>>n>>m;
for(int i=1;i<=m;i++) {
cin>>e[i].x>>e[i].y;
int x=e[i].x,y=e[i].y;
du[x]++;
du[y]++;
ans=max(ans,max(du[x],du[y]));
}
for(int i=1;i<=n;i++) id[i]=i;
//sort(id+1,id+1+n,cmp);
for(int i=1;i<=ans;i++) {
memset(link,0,sizeof link);
sort(id+1,id+1+n,cmp);
for(int j=1;j<=n;j++) ve[j].clear();
for(int j=1;j<=m;j++) {
if(!col[e[j].x][e[j].y]) {
ve[e[j].x].push_back(e[j].y);
ve[e[j].y].push_back(e[j].x);
}
}
for(int j=1;j<=n;j++) {
if(!link[id[j]]) {
++timecnt;
dfs(id[j]);
}
}
for(int j=1;j<=n;j++) {
if(link[j]) {
col[j][link[j]]=i;
du[j]--;
}
}
}
cout<<ans<<endl;
for(int i=1;i<=m;i++) {
cout<<col[e[i].x][e[i].y]<<endl;
}
return 0;
}