题意:
某土豪公司创建了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; }