zoukankan      html  css  js  c++  java
  • [CF1142E] Pink Floyd

    传送门


    题意:一个(n)个点的竞赛图,给出(m)条红色的边,其方向确定,其余边均为绿色,方向未知。你可以询问不超过(2n)次,每次询问一条绿色边的方向。要求找到一个点(x),使得(x)出发到任意一个点都有至少一条同色路径。(n ,mleq 10^5)。可能会在交互过程中动态构造图。


    考虑没有红色的边时怎么做。显然在询问过程中会形成若干棵绿色的外向树,每次询问两棵外向树的树根,将它们合并起来即可。最后剩余的点即为答案。

    回到原题,发现由于红色边的存在导致有些边无法通过询问定向,但是红色边本身可以作为连通的方式。

    将红色连通块缩点,发现此时任何没有红色入度的点均与上文中的绿色外向树等价,即,这些点满足可以任意询问两两之间的边,且这样的点只剩一个时即为答案。

    另一个值得注意的点是,合并时被删除的点可能会有若干红色出边,此时需遍历这些边,并将新的满足条件的点加入待处理点集中。

    Code:

    #include <queue>
    #include <cstdio>
    #include <cctype>
    #include <cassert>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define R register
    #define ll long long
    using namespace std;
    const int N = 110000;
    
    int hd[N], nxt[N], to[N], dfn[N], low[N], scc[N], dgrV[N], dgrS[N], stck[N], instck[N], rep[N];
    int n, m, cnt, tot, noedg = 1, top;
    queue<int> que;
    
    template <class T> inline void read(T &x) {
        x = 0;
        char ch = getchar(), w = 0;
        while (!isdigit(ch))
            w = (ch == '-'), ch = getchar();
        while (isdigit(ch))
            x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
        x = w ? -x : x;
        return;
    }
    
    inline void addEdg(int x, int y) {
        nxt[++noedg] = hd[x], hd[x] = noedg, to[noedg] = y;
        return;
    }
    
    void tarjan(int now) {
        dfn[now] = low[now] = ++cnt;
        stck[++top] = now, instck[now] = 1;
        for (R int i = hd[now]; i; i = nxt[i]) {
            int v = to[i];
            if (dfn[v]) {
                if (instck[v]) low[now] = min(low[now], dfn[v]);
            }
            else
                tarjan(v), low[now] = min(low[now], low[v]);
        }
        if (dfn[now] == low[now]) {
            rep[++tot] = now;
            while (stck[top] != now)
                instck[stck[top]] = 0, scc[stck[top--]] = tot;
            instck[now] = 0, scc[stck[top--]] = tot;
        }
        return;
    }
    
    inline void del(int x) {
        for (R int i = hd[x], v; i; i = nxt[i]) {
            if (scc[v = to[i]] != scc[x]) {
                if (!--dgrS[scc[v]]) que.push(rep[scc[v]]);
            }
            else if (!--dgrV[v] && v != rep[scc[v]]) que.push(v);
        }
        return;
    }
    
    int main() {
        int x, y;
        read(n), read(m);
        for (R int i = 1; i <= m; ++i)
            read(x), read(y), addEdg(x, y);
        for (R int i = 1; i <= n; ++i)
            if (!dfn[i])
                tarjan(i);
        for (R int i = 1; i <= n; ++i)
            for (R int j = hd[i], v; j; j = nxt[j])
                if (scc[v = to[j]] != scc[i])
                    ++dgrS[scc[v]];
                else
                    ++dgrV[v];
        for (R int i = 1; i <= tot; ++i)
            if (!dgrS[i])
                que.push(rep[i]);
        while (que.size()) {
            if (que.size() == 1) {
                cout << "! " << que.front() << endl;
                return 0;
            }
            int a = que.front(), b;
            que.pop(), b = que.front(), que.pop();
            cout << "? " << a << ' ' << b << endl;
            read(x);
            if (x) del(b), que.push(a);
            else del(a), que.push(b);
        }
        return 0;
    }
    
  • 相关阅读:
    20155322 2017-2018-1《信息安全系统设计》第七周学习总结
    20155322 2017-2018-1《信息安全系统设计》实验二:固件程序设计
    20155322 2017-2018-1《信息安全系统设计》第六周学习总结
    20155322 2017-2018-1《信息安全系统设计》第六周 课下作业
    01--DNS服务器1
    华为lab-rs-v1-2.5_流量优化
    华为lab-rs-v1-2.4_OSPF提升
    华为lab-rs-v1-2.3_OSPF基础
    华为lab-rs-v1-2.2_RIP基础
    华为lab-rs-v1-2.1_IP基础
  • 原文地址:https://www.cnblogs.com/suwakow/p/11402331.html
Copyright © 2011-2022 走看看