题目描述
给一个没有重边的二分图, 要求给边染色. 有公共点的边不能同色. 问最少用多少种颜色, 并任意构造一组方案.
输入描述:
第一行两个数n和m表示图的点数和边数(0<n<1001,0<m<2001).
之后m行每行2个数表示一条边的两个端点. 点从1编号到n.
保证给的是二分图.
输出描述:
第一行一个数k表示需要多少种颜***r>接下来m行每行一个数表示输入的边的颜色. 按照输入的顺序输出, 颜色从1编号到k.
题解
用公共点的边不同色,即从一个点出来的边颜色不同。二分图里有一个定理,二分图边着色所需最小颜色数,等于图中点的最大度数。
现在的问题就是我们怎样去构造染色方法。有公共点的边不能同色,那么如果我们每次找到的这条边,他的两个端点在这次查找中都没出现过的话,这样的一组边就可以用相同颜色来染色了。找到的边在这次查找中都没出现过,其实就相当于对二分图进行匹配。
所以我们多次调用匈牙利算法进行匹配,每次匹配出来的一组边染上相同的颜色即可。
但要注意的是我们每次匹配的时候要从最大度数的点进行匹配,否则可能度数小的点都把度数大的点所能匹配的点匹配了,那么这次过后对于度数大的点所需要的染色数量仍然没有改变,结果就不是最优的了。以上困惑了我好久,经过询问大佬才明白
代码
#include<iostream> #include<algorithm> #include<map> #include<vector> #include<set> #include<string> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #include<stack> using namespace std; #define ll long long #define ull unsigned long long #define pb push_back #define pii pair<int,int> #define all(A) A.begin(), A.end() #define fi first #define se second #define MP make_pair #define rep(i,n) for(register int i=0;i<(n);++i) #define repi(i,a,b) for(register int i=int(a);i<=(b);++i) #define repr(i,b,a) for(register int i=int(b);i>=(a);--i) template<typename T> inline T read(){ T s=0,f=1; char ch = getchar(); while(!isdigit(ch)) {if(ch == '-') f=-1;ch = getchar();} while(isdigit(ch)) {s=(s<<3)+(s<<1)+ch-48;ch = getchar();} return s*f; } #define gn() read<int>() #define gl() read<ll>() template<typename T> inline void print(T x) { if(x<0) putchar('-'), x=-x; if(x>9) print(x/10); putchar(x%10+'0'); } //////////////////////////////////////////////////////////////////////// const int N=2010; int used[N],nxt[N],color[N][N],l[N],r[N],degree[N],idx[N]; vector<int> v[N]; int n,m,ans; bool match(int x){ for(auto k:v[x]){ if(!used[k]){ used[k]=1; if(nxt[k]==0||match(nxt[k])){ nxt[k]=x;nxt[x]=k; return true; } } } return false; } //////////////////////////////////////////////////////////////////////// int main(){ n=gn(),m=gn(); repi(i,1,m){ l[i]=gn(),r[i]=gn(); ans=max(ans,++degree[l[i]]); ans=max(ans,++degree[r[i]]); } printf("%d\n",ans); repi(i,1,n)idx[i]=i; repi(i,1,ans){ repi(j,1,m){ if(!color[l[j]][r[j]]){ v[l[j]].pb(r[j]); v[r[j]].pb(l[j]); } } repi(j,1,n){ nxt[j]=0; } sort(idx+1,idx+1+n,[](int x,int y){ return degree[x]>degree[y]; }); repi(j,1,n){ if(!nxt[idx[j]]){ memset(used,0,sizeof(used)); match(idx[j]); } } repi(j,1,n){ if(nxt[j]){ color[j][nxt[j]]=i; --degree[j]; } v[j].clear(); } } repi(i,1,m){ print(color[l[i]][r[i]]),putchar(10); } } /** * In every life we have some trouble * When you worry you make it double * Don't worry,be happy. **/