zoukankan      html  css  js  c++  java
  • Codeforces 950E Data Center Maintenance 强连通分量

    题目链接

    题意

    (n)个信息中心,每个信息中心都有自己的维护时间((0leq tlt h)),在这个时刻里面的信息不能被获得。

    每个用户的数据都有两份备份,放在两个相异的信息中心(维护时间也相异)。

    现要挑选出信息中心的一个尽量小的子集,使得将这个子集的维护时间向后推移一个小时后,不会导致问题(存在一个用户,其数据所在的两个信息中心维护时间相同)。

    思路

    强连通分量

    考虑每个用户的信息存放的两个信息中心,(u,v)
    如果调整其中任何一个的时间不会导致与另外一个产生冲突,就说明是安全的;
    否则若(u)调整后与(v)产生冲突,则一旦调整(u)就必须调整(v),于是加一条边(<u,v>).

    在得到的图上跑(tarjan)再缩点后得到强连通分量,答案就是新的图中 出度为(0)的并且(size)最小 的一块(SCC)。道理显然。

    Code

    #include <bits/stdc++.h>
    #define F(i, a, b) for (int i = (a); i < (b); ++i)
    #define F2(i, a, b) for (int i = (a); i <= (b); ++i)
    #define dF(i, a, b) for (int i = (a); i > (b); --i)
    #define dF2(i, a, b) for (int i = (a); i >= (b); --i)
    #define maxn 100010
    using namespace std;
    typedef long long LL;
    int dfn[maxn], low[maxn], ne[maxn], belong[maxn], a[maxn], sz[maxn], scc, cnt, tot, outd[maxn];
    stack<int> s;
    bool in[maxn];
    struct Edge { int from, to, ne; }edge[maxn<<1];
    void add(int u, int v) {
        edge[tot] = {u, v, ne[u]};
        ne[u] = tot++;
    }
    void tarjan(int u) {
        dfn[u] = low[u] = ++cnt;
        in[u] = true;
        s.push(u);
        for (int i = ne[u]; ~i; i = edge[i].ne) {
            int v = edge[i].to;
            if (!dfn[v]) {
                tarjan(v);
                low[u] = min(low[u], low[v]);
            }
            else if (in[v]) low[u] = min(low[u], dfn[v]);
        }
        if (low[u]==dfn[u]) {
            ++scc;
            while (true) {
                int v = s.top(); in[v] = false; s.pop();
                belong[v] = scc; ++sz[scc];
                if (u==v) break;
            }
        }
    }
    void contrast() {
        F(i, 0, tot) {
            int u = edge[i].from, v = edge[i].to;
            if (belong[u]==belong[v]) continue;
            ++outd[belong[u]];
        }
    }
    int main() {
        memset(ne, -1, sizeof ne);
        int n, m, h, u, v;
        scanf("%d%d%d", &n, &m, &h);
        F2(i, 1, n) scanf("%d", &a[i]);
        F(i, 0, m) {
            scanf("%d%d", &u,&v);
            if (a[u]>a[v]) swap(u, v);
            if (a[v]-a[u]==1) add(u, v);
            if (a[v]-a[u]==h-1) add(v, u);
        }
        F2(i, 1, n) if (!dfn[i]) tarjan(i);
        contrast();
        int ans=n+1, p=-1;
        F2(i, 1, scc) {
            if (!outd[i]) {
                if (sz[i]<ans) ans=sz[i], p=i;
            }
        }
        printf("%d
    ", ans);
        F2(i, 1, n) if (belong[i]==p) printf("%d ", i); puts("");
        return 0;
    }
    
    
  • 相关阅读:
    654. Maximum Binary Tree
    764. Largest Plus Sign
    763. Partition Labels
    dasd
    IT项目管理——《人月神话》读后感
    计算机网络实验八实验报告——应用Packet Tracer 5.0模拟器工具对WLAN进行配置
    Explain分析查询语句
    ​二十种实战调优MySQL性能优化的经验
    查询优化 | MySQL慢查询优化
    InnoDB并发事务
  • 原文地址:https://www.cnblogs.com/kkkkahlua/p/8541916.html
Copyright © 2011-2022 走看看