CF 600F( 二分图
题目:给一个二分图,对每条边进行染色,求一种使得相邻边颜色都不同并且所用颜色最少的染色方案.
思路:颜色最少个数大于等于度最大的点的度数,然后要构造出一种染色方案.构造方法类似于二分匹配的搜索算法.对于每个点,记录与这个点相连的对应颜色的点,然后每次取最小的没有使用的颜色,如果颜色有冲突,对于两个点x,y,有cx没有在x的邻边出现,cy没有在y的邻边出现,把xy染成cx,然后冲突的边染色成cy,如果还有冲突,则用cx继续染色,由于是二分图没有奇环,所以必然可以最终找到替代方案.写法上有些技巧,参考了cf上红名巨巨的代码.
/* * 没有过去,也没有未来 */ #pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <map> #include <algorithm> #include <cstdio> #include <cstring> #include <cstdlib> #include <vector> #include <queue> #include <stack> #include <functional> #include <set> #include <cmath> using namespace std; #define IOS std::ios::sync_with_stdio (false);std::cin.tie(0) #define pb push_back #define PB pop_back #define bk back() #define fs first #define se second #define sq(x) (x)*(x) #define eps (1e-10) #define INF (0x3f3f3f3f) #define clr(x) memset((x),0,sizeof (x)) #define cp(a,b) memcpy((a),(b),sizeof (b)) typedef long long ll; typedef unsigned long long ull; typedef pair<ll,ll> P; const int maxn=1005; int linkx[maxn][maxn],linky[maxn][maxn]; int id[maxn][maxn]; int d[maxn*3]; int a,b,m; int ans[maxn*maxn]; int main(){ //freopen("/home/slyfc/CppFiles/in","r",stdin); //freopen("/home/slyfc/CppFiles/out","w",stdout); memset(linkx,-1,sizeof linkx); memset(linky,-1,sizeof linky); memset(id,-1,sizeof id); cin>>a>>b>>m; int maxd=0; for(int e=0;e<m;e++){ int x,y; scanf("%d%d",&x,&y); d[x]++,d[y+a]++; maxd=max(maxd,d[x]); maxd=max(maxd,d[y+a]); id[x][y]=e; int cx=0,cy=0; while(linkx[x][cx]!=-1) cx++; while(linky[y][cy]!=-1) cy++; if(cx==cy){ linkx[x][cx]=y; linky[y][cy]=x; }else{ int left=x; int right=y; linkx[x][cx]=y; for(;;){ int tmp=linky[right][cx]; linky[right][cx]=left; linky[right][cy]=tmp; if(tmp==-1) break; int tmp0=linkx[tmp][cy]; linkx[tmp][cy]=right; linkx[tmp][cx]=tmp0; if(tmp0==-1) break; left=tmp,right=tmp0; } } } cout<<maxd<<endl; for(int i=0;i<maxn;i++){ for(int j=0;j<maxn;j++){ if(linkx[i][j]!=-1){ int y=linkx[i][j]; ans[id[i][y]]=j+1; } } } for(int i=0;i<m;i++){ printf("%d ",ans[i]); } return 0; }