uva10614

题意:

给*的位置涂色,保证不同行不同列的涂色不同

思路:

关键思路我已经标在代码上了

一共要涂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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值