ZOJ 3780 Paint the Grid Again
拓扑排序。2014浙江省赛题。
先看行:
如果这行没有黑色,那么这个行操作肯定不操作。
如果这行全是黑色,那么看每一列,如果列上有白色,那么这一列连一条边到这一行,代表这一列画完才画那一行
如果不全是黑色,那么看这一行的每一个元素,如果有白色的,那么白色所在列向这一行连边。
再看列:
与看行类似,不再赘述。
建图建完之后进行拓扑排序。
#include<cstdio> #include<cstring> #include<cmath> #include<string> #include<vector> #include<queue> #include<algorithm> #include<iostream> using namespace std; const int maxn = 500 + 10; int T, n; char s[maxn][maxn]; int G[2 * maxn][2 * maxn]; vector<int>g[2 * maxn]; bool flag[2 * maxn]; int tot[2 * maxn]; int w[maxn], b[maxn]; struct cmp{ bool operator ()(int &a, int &b){ return a>b;//最小值优先 } }; priority_queue<int, vector<int>, cmp>Q;//最小值优先 vector<int>ans; void init() { memset(G, -1, sizeof G); for (int i = 0; i <= 2 * n; i++) g[i].clear(); memset(flag, 1, sizeof flag); memset(tot, 0, sizeof tot); while (!Q.empty()) Q.pop(); ans.clear(); for (int i = 0; i<n; i++) { int sum = 0; for (int j = 0; j<n; j++) if (s[i][j] == 'X') sum++; b[i] = sum; } for (int j = 0; j<n; j++) { int sum = 0; for (int i = 0; i<n; i++) if (s[i][j] == 'O') sum++; w[j] = sum; } } void read() { scanf("%d", &n); for (int i = 0; i<n; i++) scanf("%s", s[i]); } void work() { for (int i = 0; i<n; i++) { if (b[i] == 0) flag[i + n] = 0; else if (b[i] == n) { for (int j = 0; j<n; j++) if (w[j]) G[j][i + n] = 1; } else { for (int j = 0; j<n; j++) if (s[i][j] == 'O') G[i + n][j] = 1; } } for (int j = 0; j<n; j++) { if (w[j] == 0) flag[j] = 0; else if (w[j] == n) { for (int i = 0; i<n; i++) if (b[i]) G[i + n][j] = 1; } else { for (int i = 0; i<n; i++) if (s[i][j] == 'X') G[j][i + n] = 1; } } for (int x = 0; x<2 * n; x++) for (int y = 0; y<2 * n; y++) if (G[x][y] == 1) { tot[y]++; g[x].push_back(y); } for (int i = 0; i<2 * n; i++) if (flag[i] && tot[i] == 0) Q.push(i); while (!Q.empty()) { int top = Q.top(); Q.pop(); ans.push_back(top); for (int i = 0; i<g[top].size(); i++) { tot[g[top][i]]--; if (tot[g[top][i]] == 0) Q.push(g[top][i]); } } if (ans.size()<n) printf("No solution\n"); else { for (int i = 0; i<ans.size(); i++) { if (ans[i] >= 0 && ans[i] <= n - 1) printf("C%d", ans[i] + 1); else printf("R%d", ans[i] - n + 1); if (i<ans.size() - 1) printf(" "); else printf("\n"); } } } int main() { scanf("%d", &T); while (T--) { read(); init(); work(); } return 0; }