CF 949C Data Center Maintenance_強聯通份量_思惟題

題意:
某土豪公司創建了n個數據中心,把m份資料每份在其中的兩個數據中心備份。 每一個數據中心在一天h個小時當中有一個小時須要維護,此時不提供資料下載服務。 如今土豪公司想要將其中若干個數據中心的維護時間向後推遲一小時,並要求一天中任意時刻每份資料均可以被下載,問最少選取多少個數據中心維護。spa

題解:
首先,對於兩個備份的地方,咱們發現只有 (C[a]+1)(C[a]+1)(C[a]+1) % h==C[b]h==C[b]h==C[b] 時,a,ba,ba,b 兩個處理器須要同時後延一小時。因而,建圖的條件就是隻要 (C[a]+1)(C[a]+1)(C[a]+1) % h==C[b])h==C[b])h==C[b]) 就在 (a,b)(a,b)(a,b) 之間連一條邊,跑一遍 tarjantarjantarjan 求出出度爲 000 的大小最小的團便可。code

Code:get

#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\n", siz[ans]);
        for(int i = 1;i <= n; ++i)
        {
            if(answer[i] == ans) printf("%d ",i);
        }
        printf("\n");
    }
}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;
}
相關文章
相關標籤/搜索