题意:
有n个数据中心,m个客户,每天有h个小时,其中 n,m,h<=100000。每个数据中心i每天都会有一个数据维护的时间0<=u[i]<=h-1,在数据中心维护期间时不可以使用的。每个客户都选择两个不同的数据中心,以保证每天的数据使用不间断。保证初始时符合要求。找出最少的数据中心数,使每个数据中心的维护时间推迟一个小时(若u[i]<h-1推迟一小时变为u[i]+1,否则变为0),每个客户都能正常使用。
分析:
我们发现,只要每个客户选择的两个数据中心的维护时间不同就符合题目的要求。如果其中一个刚好比另一个提前一个小时,那么如果要推迟这一个显然不符合要求。我们就可以建一个图,若某个客户的两个数据中心i,j中的一个可以通过推迟一小时使得u[i]=u[j],那么就从i到j连一条有向边。然后tarjan缩点,我们会发现,我们只要找出缩点后的图中所有出度为0的联通分量中点数最少的,这就是答案。插一句···tarjan曾经是中学的我“背”的最熟的代码之一
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <vector> 6 #include <stack> 7 #include <queue> 8 using namespace std; 9 const int maxn=100000+100; 10 const int INF=2147000000; 11 vector<int>G[maxn]; 12 vector<int>SCC[maxn]; 13 int u[maxn],c[maxn][2]; 14 int in[maxn]; 15 int n,m,h; 16 int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt; 17 stack<int>S; 18 void dfs(int u){ 19 pre[u]=lowlink[u]=++dfs_clock; 20 S.push(u); 21 for(int i=0;i<G[u].size();i++){ 22 int v=G[u][i]; 23 if(!pre[v]){ 24 dfs(v); 25 lowlink[u]=min(lowlink[u],lowlink[v]); 26 }else if(!sccno[v]){ 27 lowlink[u]=min(lowlink[u],pre[v]); 28 } 29 } 30 if(lowlink[u]==pre[u]){ 31 scc_cnt++; 32 SCC[scc_cnt].clear(); 33 for(;;){ 34 int x=S.top();S.pop(); 35 sccno[x]=scc_cnt; 36 SCC[scc_cnt].push_back(x); 37 if(x==u)break; 38 } 39 } 40 } 41 void find_scc(int n){ 42 dfs_clock=scc_cnt=0; 43 memset(sccno,0,sizeof(sccno)); 44 memset(pre,0,sizeof(pre)); 45 for(int i=1;i<=n;i++) 46 if(!pre[i])dfs(i); 47 } 48 int main(){ 49 scanf("%d%d%d",&n,&m,&h); 50 for(int i=1;i<=n;i++)scanf("%d",&u[i]); 51 for(int i=1;i<=m;i++){ 52 scanf("%d%d",&c[i][0],&c[i][1]); 53 if(u[c[i][0]]>u[c[i][1]])swap(c[i][0],c[i][1]); 54 if(u[c[i][0]]+1==u[c[i][1]]) 55 G[c[i][0]].push_back(c[i][1]); 56 if(u[c[i][0]]==0&&u[c[i][1]]==h-1) 57 G[c[i][1]].push_back(c[i][0]); 58 } 59 find_scc(n); 60 int ans=0; 61 int Min=INF; 62 63 for(int i=1;i<=n;i++){ 64 for(int j=0;j<G[i].size();j++){ 65 int v=G[i][j]; 66 if(sccno[i]!=sccno[v]) 67 in[sccno[i]]++; 68 } 69 } 70 71 for(int i=1;i<=scc_cnt;i++){ 72 if(!in[i]){ 73 if(Min>SCC[i].size()){ 74 Min=SCC[i].size(); 75 ans=i; 76 } 77 } 78 } 79 printf("%d ",Min); 80 for(int i=0;i<SCC[ans].size();i++) 81 printf("%d ",SCC[ans][i]); 82 return 0; 83 }