• [拓扑排序] 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判断是否有环应该也可行。

  • 相关阅读:
    leetcode931
    leetcode1289
    leetcode1286
    poj Meteor Shower
    noip杂题题解
    noip2007部分题
    NOIP Mayan游戏
    某模拟题题解
    codevs 1423 骑士
    noip 邮票面值设计
  • 原文地址:https://www.cnblogs.com/JMDWQ/p/2624875.html
Copyright © 2020-2023  润新知