[拓扑排序] PKU 2585 Window Pains

拓扑排序判断有向图是否有环,1A啊!!!

对每个位置(前3行前3列),如果它控制范围内的某个位置上为 j ,而这个位置原始值为 i ,则添加一条 i 到 j 的边,如果出现环则说明电脑出问题了;

不知道数据中是否含有非法的,所以就加了个判断:判断是否出现了非法状态,即某个位置出现了不属于这个位置的数字。

# include <cstdio>

# include <cstring>



# define N 5

# define NS ((N-1)*(N-1)) + 1



const int n = 3;

const int m = 9;

int in[NS];

int f[N][N];

char g[NS][NS];



void add(int i, int j)

{

    if (!g[j][i])

    {

        g[j][i] = 1;

        ++in[i];

    }

}



void build(void)

{

    memset(g, 0, sizeof(g));

    memset(in, 0, sizeof(in));

    int i, j, t, k;

    for (i = 1; i <= n; ++i)

    for (j = 1; j <= n; ++j)

    {

        k = j+(i-1)*n;

        if (f[i][j]     != k)    add(f[i][j]     ,k);

        if (f[i+1][j]   != k)    add(f[i+1][j]   ,k);

        if (f[i][j+1]   != k)    add(f[i][j+1]   ,k);

        if (f[i+1][j+1] != k)    add(f[i+1][j+1] ,k);

    }

}



int topsort(void)

{

    int cnt = 0;

    char vis[NS];

    memset(vis, 0, sizeof(vis));

    //for(int i = 1; i <= m; ++i)    printf("indegrees[%d] = %d\n", i, in[i]);

    while (cnt < m)

    {

        int c = 0;

        for (int i = 1; i <= m; ++i) if(!vis[i] && !in[i])

        {

            ++c;

            vis[i] = 1;

            for (int j = 1; j <= m; ++j) if (g[i][j])

                --in[j];

            break;

        }

        if (c == 0) return -1;

        ++cnt;

    }

    return 0;

}



bool check(void)

{

    if(f[1][1] != 1 && f[1][n+1] != 3 || f[n+1][1] != 7 || f[n+1][n+1] != 9)

    {

        return false;

    }

    if (f[1][2]!=1 && f[1][2]!=2) {return false;}

    if (f[2][1]!=1 && f[2][1]!=4) {return false;}

    if (f[1][3]!=2 && f[1][3]!=3) {return false;}

    if (f[3][1]!=4 && f[3][1]!=7) {return false;}

    if (f[2][2]!=1 && f[2][2]!=2 && f[2][2]!=4 && f[2][2]!=5) {return false;}

    if (f[2][3]!=2 && f[2][3]!=3 && f[2][3]!=5 && f[2][3]!=6) {return false;}

    if (f[3][2]!=7 && f[3][2]!=8 && f[3][2]!=4 && f[3][2]!=5) {return false;}

    if (f[3][3]!=9 && f[3][3]!=6 && f[3][3]!=5 && f[3][3]!=8) {return false;}

}



void solve()

{

    if (check() == false)

    {

        puts("THESE WINDOWS ARE BROKEN");

        return ;

    }

    int ans = topsort();

    if (ans == -1)

        puts("THESE WINDOWS ARE BROKEN");

    else

        puts("THESE WINDOWS ARE CLEAN");

}



int main()

{    

    char s[20];

    while (scanf("%s", s), strcmp(s, "ENDOFINPUT")!=0)

    {

        for (int i = 1; i <= n+1; ++i)

        for (int j = 1; j <= n+1; ++j)

            scanf("%d", &f[i][j]);

        build();

        solve();

        scanf("%s", s);

    }

    

    return 0;

}

直接DFS判断是否有环应该也可行。

你可能感兴趣的:(window)