zoukankan      html  css  js  c++  java
  • bzoj3440:传球游戏

    Pre

    真的毒瘤题,昨天晚上以为是一道简单的图论题,今天中午没有调出来,晚上我选择看题解发现漏了一种情况。

    于是

    就花了一晚上调程序。

    现在时间(21:31)

    Solution

    拆点是很容易想到的。

    拓扑((Tarjan)应该也可以,没试过)找环。

    之后分类。

    有一个点在环内就不符合。

    若两个点都不在环内,需要对图重建,之后染色判断这两个点是否有父子关系。

    不知不觉就快200行代码(以下的代码有删减)。

    Code

    #include <bits/stdc++.h>
    #define ll long long
    #define ull unsigned long long
    #define xx first
    #define yy second
     
    using namespace std;
     
    const int N = 1000000 + 5, M = N << 1;
    int suf[M], n;
    int fr[M << 1], to[M << 1], h[M], tot;
     
    inline void add (int u, int v) {
        tot++;
        fr[tot] = h[u];
        to[tot] = v;
        h[u] = tot;
    }
     
    inline int qian (int x) {
        x--;
        while (x <= n) {
            x += n;
        }
        return x;
    }
     
    inline int hou (int x) {
        x++;
        while (x > n) {
            x -= n;
        }
        return x;
    }
     
    queue<int> Q;
    int rd[M];
    bool type[M];
     
    inline void Top () {
        for (int i = 1; i <= n * 2; ++i) {
            if (!rd[i]) {
                Q.push (i);
            }
        }
        while (Q.size ()) {
            int tmp = Q.front();
            Q.pop();
            type[tmp] = 1;
            rd[suf[tmp]]--;
            if (!rd[suf[tmp]]) {
                Q.push(suf[tmp]);
            }
        }
    }
     
    int it[M], color[M], cocnt;
    bool ins[M], fatin[N];
     
    inline void dfs (int u) {
        if (u <= n * 2) {
            ins[u] = 1;
        }
        int ne = u > n ? u - n : u + n;
        if (ins[ne]) {
            fatin[min (u, ne)] = 1;
        }
        for (int i = h[u]; i; i = fr[i]) {
            if (u > n * 2) {
                color[to[i]] = u - n * 2;
            }
            else {
                color[to[i]] = color[u];
            }
            dfs (to[i]);
        }
        ins[u] = 0;
    }
     
    inline void Rebuild () {
        for (int i = 1; i <= n * 2; ++i) {
            it[i] = type[i] ^ 1;
            type[i] ^= 1;
        }
        for (int i = 1; i <= n * 2; ++i) {
            if (it[i]) {
                cocnt++;
                for (int j = suf[i]; j != i; j = suf[j]) {
                    color[j] = cocnt;
                    it[j] = 0;
                }
                color[i] = cocnt;
                it[i] = 0;
            }
        }
        for (int i = 1; i <= n * 2; ++i) {
            if (type[i]) {
                continue;
            }
            if (!type[suf[i]]) {
                add (suf[i], i);
            }
            else{
                add (color[suf[i]] + n * 2, i);
            }
        }
        for (int i = 1; i <= cocnt; ++i) {
            dfs (n * 2 + i);
        }
    }
     
    int main () {
        memset (type, 0, sizeof (type));
        scanf ("%d", &n);
        for (int i = 1; i <= n; ++i) {
            int tmp;
            scanf ("%d", &tmp);
            if (tmp == 1) {
                suf[i] = hou (i);
                suf[i + n] = qian (i);
            }
            else if (tmp == 2) {
                suf[i] = qian (i);
                suf[i + n] = hou (i);
            }
            else if (tmp == 3) {
                suf[i] = hou (hou (i));
                suf[i + n] = qian (qian (i));
            }
            else if (tmp == 4) {
                suf[i] = qian (qian (i));
                suf[i + n] = hou (hou (i));
            }
            rd[suf[i]]++;
            rd[suf[i + n]]++;
        }
        Top ();
        Rebuild ();
        int ans = 0;
        for (int i = 1; i <= n; ++i) {
            if (type[i] || type[i + n]) {
                continue;
            }
            if (!type[i] && !type[i] && fatin[i]) {
                continue;
            }
            ans++;
        }
        printf ("%d
    ", ans);
        for (int i = 1; i <= n; ++i) {
            if (type[i] || type[i + n]) {
                continue;
            }
            if (!type[i] && !type[i] && fatin[i]) {
                continue;
            }
            printf ("%d", i);
            ans--;
            if (ans) {
                printf (" ");
            }
        }
        printf ("
    ");
        return 0;
    }
    

    Conslusion

    记住有向图找环用拓扑挺方便的。

    学到了染色重建图的方法,有一点细节。真的是一点

  • 相关阅读:
    查询避免Unknown column ‘xxx’ in ‘where clause
    Spring依赖循环:The dependencies of some of the beans in the application context form a cycle
    POJ(北京大学)刷题导航
    ACM使用Java提交总是超时的解决方法
    申请了服务器,建立了新博客。 不在用这个了。
    jeecg数据库添加字段后表单的修改
    jeecg普通表和数据字典的关联
    jeecg添加滚动图
    jeecg定时任务的bug记录
    classpath究竟是指哪里?
  • 原文地址:https://www.cnblogs.com/ChiTongZ/p/11153986.html
Copyright © 2011-2022 走看看