• CF 949C Data Center Maintenance_强联通分量_思维题


    题意:
    某土豪公司建立了n个数据中心,把m份资料每份在其中的两个数据中心备份。 每个数据中心在一天h个小时当中有一个小时需要维护,此时不提供资料下载服务。 现在土豪公司想要将其中若干个数据中心的维护时间向后推迟一小时,并要求一天中任意时刻每份资料都可以被下载,问最少选取多少个数据中心维护。

    题解:
    首先,对于两个备份的地方,我们发现只有 (C[a]+1)(C[a]+1) % h==C[b]h==C[b] 时,a,ba,b 两个处理器需要同时后延一小时。于是,建图的条件就是只要 (C[a]+1)(C[a]+1) % h==C[b])h==C[b]) 就在 (a,b)(a,b) 之间连一条边,跑一遍 tarjantarjan 求出出度为 00 的大小最小的团即可。

    Code:

    #include<cstdio>
    #include<algorithm>
    #include<stack>
    #include<vector>
    using namespace std;
    const int maxn = 1000000 + 5;
    int n,m, h, C[maxn];
    int head[maxn], to[maxn << 1], nex[maxn << 1], cnt, degree[maxn];
    int dfn[maxn], low[maxn], scc, siz[maxn], idx, vis[maxn], answer[maxn], ans;
    stack<int>S;
    inline void get_min(int &a, int b){ if(a > b) a = b;}
    struct Graph{
        inline void add_edge(int u,int v){
            nex[++cnt] = head[u];
            head[u] = cnt;
            to[cnt] = v;
        }
        void tarjan(int u){
            low[u] = dfn[u] = ++scc;
            S.push(u);
            vis[u] = 1;
            for(int v = head[u]; v ; v = nex[v])
            {
                if(!vis[to[v]])
                {
                    tarjan(to[v]);
                    low[u] = min(low[u], low[to[v]]); 
                }
                else if(!answer[to[v]]) get_min(low[u], dfn[to[v]]);
            }
            if(dfn[u] == low[u])
            {
                ++idx;
                for(;;)
                {
                    int x = S.top(); S.pop();
                    answer[x] = idx;
                    ++siz[idx];
                    if(u == x) break;
                }
            }
        }
        inline void solve(){
            siz[0] = maxn;
            for(int i = 1;i <= n; ++i) if(!vis[i]) tarjan(i);
            for(int i = 1;i <= n; ++i)
            {
                for(int j = head[i]; j ; j = nex[j])
                {
                    if(answer[to[j]] != answer[i]) ++degree[answer[i]];
                }
            }
            for(int i = 1;i <= idx; ++i){
                if(degree[i]) continue;
                if(siz[ans] > siz[i]) ans = i;
            }
            printf("%d
    ", siz[ans]);
            for(int i = 1;i <= n; ++i)
            {
                if(answer[i] == ans) printf("%d ",i);
            }
            printf("
    ");
        }
    }T;
    int main()
    {
        scanf("%d%d%d",&n,&m,&h);
        for(int i = 1;i <= n; ++i) scanf("%d",&C[i]);
        while(m--){
            int a,b;
            scanf("%d%d",&a,&b);
            if(((C[a] + 1) % h) == C[b]) T.add_edge(a, b);
            if(((C[b] + 1) % h) == C[a]) T.add_edge(b, a);
        }
        T.solve();
        return 0;
    }
    
  • 相关阅读:
    Datawhale编程实践(LeetCode 腾讯精选练习50)Task11
    Datawhale编程实践(LeetCode 腾讯精选练习50)Task10
    Datawhale编程实践(LeetCode 腾讯精选练习50)Task9
    Datawhale编程实践(LeetCode 腾讯精选练习50)Task8
    Datawhale编程实践(LeetCode 腾讯精选练习50)Task7
    Java多线程之三volatile与等待通知机制示例
    Java多线程之一
    [WC2021] 括号路径
    [CF1375H] Set Merging
    [CF1342E] Placing Rooks
  • 原文地址:https://www.cnblogs.com/guangheli/p/9845102.html
Copyright © 2020-2023  润新知