题意:
有一个N’N的板,刚开始板上的所有元素都是其他颜色(不是黑,也不是白),且涂得方法有两种。
1、涂一行,使该行的所有元素都变成黑色。
2.、涂一列,是该列的所有元素都变成白色。
解题思路:
我们先考虑一下两种情况,就是有一行上得元素存在白点;有一列上得元素存在黑点。
对于第一种情况,我们是否可以得到该行肯定事先涂黑的,然后在出现白点的列上,涂白,使得该行所对应列的位置存在白点。
对于第二种情况,同第一种情况。
所以我们可以把涂某一行或涂某一列看成是活动,且凃行的活动与凃列的活动之间存在明显的先后关系,所以我们可以见图,然后利用拓扑排序判断涂有无环,并再无环的条件下来算出方案。
注意:
这里需要字典序最小,所以要用优先队列
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
#define MAXN0 510
char map[MAXN0][MAXN0];
bool flagX[MAXN0],flagO[MAXN0];
vector<int>G[MAXN0<<1];
int ct[MAXN0<<1],ans[MAXN0<<1],cnt;
int N;
void init(){
int up = N<<1;
cnt = 0;
for(int i=1;i<=up;++i){
if(G[i].size()){
G[i].clear();
}
ct[i] = 0;
}
memset(flagX,false,sizeof(flagX));
memset(flagO,false,sizeof(flagO));
}
void solve(){
int up = N<<1;
priority_queue<int,vector<int>,greater<int> >pq;
for(int i=1;i<=up;++i){
if(!ct[i]){
if(G[i].size())
pq.push(i);
}
}
int st,to,sz;
while(!pq.empty()){
st = pq.top();
ans[cnt++] = st;
pq.pop();
sz = (int)G[st].size();
for(int i=0;i<sz;++i){
to = G[st][i];
--ct[to];
if(!ct[to]){
pq.push(to);
}
}
}
for(int i=1;i<=up;++i){
if(ct[i]){
printf("No solution\n");
return;
}
}
if(ans[0]>=1&&ans[0]<=N){
printf("C%d",ans[0]);
}
else{
printf("R%d",ans[0]-N);
}
for(int i=1;i<cnt;++i){
if(ans[i]>=1&&ans[i]<=N){
printf(" C%d",ans[i]);
}
else{
printf(" R%d",ans[i]-N);
}
}
puts("");
}
int main(){
int T;
while(scanf("%d",&T)!=EOF){
while(T--){
init();
scanf("%d",&N);
for(int i=1;i<=N;++i){
scanf("%s",map[i]+1);
for(int j=1;j<=N;++j){
if(map[i][j]=='X'){
flagX[i] = true;
}
else {
flagO[j] = true;
}
}
}
for(int i=1;i<=N;++i){
if(flagX[i]){
for(int j=1;j<=N;++j){
if(map[i][j]=='O'){
G[N+i].push_back(j);
++ct[j];
}
}
}
if(flagO[i]){
for(int j=1;j<=N;++j){
if(map[j][i]=='X'){
G[i].push_back(j+N);
++ct[j+N];
}
}
}
}
solve();
}
}
return 0;
}