题意:
给*的位置涂色,保证不同行不同列的涂色不同
思路:
关键思路我已经标在代码上了
一共要涂k种颜色,那么就要选出k条完全匹配的路(这样理解, 一旦这个点的横纵坐标相连,那么这两座标将不再参与匹配,即不能有相同行相同列的点)
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
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) {//一共涂k种颜色
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;
}