UVA-10615 Rooks (二分图匹配)
题目大意:在一个nxn的方格中,有些位置有车,要给每一个车都涂上颜色,使得同一行和同一列的任意两个车颜色不同,求一种需要颜色种数最少的涂色方案。
题目分析:所需的最少颜色种数是显然就能得出的,假设最少颜色种数为k。如果位置(i,j)是车,那么连一条边i->j,得到一张二分图,进行k次匹配即可构造出解。
AC代码:
# include<iostream> # include<cstdio> # include<vector> # include<cstring> # include<algorithm> using namespace std; # define REP(i,s,n) for(int i=s;i<n;++i) # define CL(a,b) memset(a,b,sizeof(a)) # define CLL(a,b,n) fill(a,a+n,b) const int N=105; int inr[N],inc[N],vis[N],link[N],ans[N][N],n; char p[N][N]; vector<int>G[N]; bool dfs(int x) { REP(i,0,G[x].size()){ int y=G[x][i]; if(vis[y]) continue; vis[y]=1; if(link[y]==-1||dfs(link[y])){ link[y]=x; return true; } } return false; } void match() { CL(link,-1); REP(i,0,n){ CL(vis,0); dfs(i); } } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d",&n); REP(i,0,n) G[i].clear(); REP(i,0,n) scanf("%s",p[i]); CL(inr,0); CL(inc,0); REP(i,0,n) REP(j,0,n) if(p[i][j]=='*'){ ++inr[i]; ++inc[j]; G[i].push_back(j); } int maxn=0; REP(i,0,n) maxn=max(maxn,max(inr[i],inc[i])); REP(i,0,n) if(inr[i]<maxn){ for(int j=0;j<n&&inr[i]<maxn;++j){ while(inr[i]<maxn&&inc[j]<maxn){ ++inr[i]; ++inc[j]; G[i].push_back(j); } } } CL(ans,0); REP(k,1,maxn+1){ match(); REP(i,0,n){ int r=link[i]; if(p[r][i]=='*') ans[r][i]=k; REP(j,0,G[r].size()) if(G[r][j]==i){ G[r].erase(G[r].begin()+j); break; } } } printf("%d\n",maxn); REP(i,0,n) REP(j,0,n) printf("%d%c",ans[i][j],(j==n-1)?'\n':' '); } return 0; }