题意: 给一个二分图染色,有公共点的边不能同色,求最小的颜色方案。
思路: 因为有公共点的边不能染同种颜色,所以,连的边最多的点就是要染的颜色数量了。 方案的求法,可以先从度最大的点开始,求出最大匹配,然后染色,之后再找下一个度最大的求最大匹配,染色。
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <string> #include <stack> #include <queue> #include <cmath> #define ll long long #define pi 3.1415927 #define inf 0x3f3f3f3f #define mod 1000000007 using namespace std; int n,m,vis[2005],mark[2005],color[2005][2005],point[2005],x[2005],y[2005],id[2005]; vector<int>res[2005]; bool cmp(int x,int y) { return point[x]>point[y]; } int dfs(int k) //最大匹配 { for(auto p:res[k]) { if(!vis[p]) { vis[p]=1; if(mark[p]==0 || dfs(mark[p])) { mark[p]=k; mark[k]=p; return 1; } } } return 0; } int main () { int T,i,t,j,k,p,sum=0,u,v,maxs; cin>>n>>m; maxs=0; for(i=1;i<=m;++i) { cin>>x[i]>>y[i]; point[x[i]]++; point[y[i]]++; maxs=max(maxs,max(point[x[i]],point[y[i]])); } for(i=1;i<=n;++i) id[i]=i; for(i=1;i<=maxs;++i) { for(j=1;j<=m;++j) if(!color[x[j]][y[j]]){ res[x[j]].push_back(y[j]); res[y[j]].push_back(x[j]); } sort(id+1,id+1+n,cmp); //按照度的大小排序 memset(mark,0,sizeof(mark)); for(t=1,k=id[t];t<=n;k=id[++t]) //从度最大的开始匹配 if(!mark[k]){ memset(vis,0,sizeof(vis)); dfs(k); } for(j=1;j<=n;++j) { if(mark[j]){ color[j][mark[j]]=i; point[j]--; } res[j].clear(); } } cout<<maxs<<endl; for(i=1;i<=m;++i) cout<<color[x[i]][y[i]]<<endl; return 0; }