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

 

posted @ 2016-02-19 15:09  Fighting_Heart  阅读(297)  评论(0编辑  收藏  举报