您的位置:首页 > 其它

UVA-10615 Rooks (二分图匹配)

2015-11-08 20:30 211 查看
题目大意:在一个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
,inc
,vis
,link
,ans

,n;
char p

;
vector<int>G
;

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;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: