CF949C Data Center Maintenance(建图+强联通分量)

题意

有 n 个信息中心,第 i 个信息中心要在第 ti 个小时维护,维护期间信息不能被获得。

每个用户的数据都有两份备份,第 i 个用户的数据放在信息中心 c(i,1) 和 c(i,2)。

现在要挑选一个尽量小的信息中心集合,使得将这个集合的维护时间推迟一个小时后,仍然能保证每个用户的数据在任意时刻都能获得。

n≤100000

题解

对于每对 c(i,1),c(i,2),若调整 c(i,1) 后与 c(i,2) 的维护时间冲突,则连边 (c(i,1), c(i,2) )
对于 c(i,2),c(i,1) 亦然
求出强连通分量,所求集合即为缩点后度数为 0 的最小的 SCC
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 const int N=500100;
 8 int cnt,head[N];
 9 int dfn[N],low[N],stack[N],vis[N],w[N],c[N],num,tot,top;
10 int n,m,h,t[N],ans,a[N],b[N],deg[N];
11 struct edge{
12     int to,nxt;
13 }e[N];
14 void add(int u,int v){
15     cnt++;
16     e[cnt].nxt=head[u];
17     e[cnt].to=v;
18     head[u]=cnt;
19 }
20 void Tarjan(int u){
21     dfn[u]=low[u]=++tot;
22     stack[++top]=u;
23     vis[u]=1;
24     for(int i=head[u];i;i=e[i].nxt){
25         int v=e[i].to;
26         if(dfn[v]==0){
27             Tarjan(v);
28             low[u]=min(low[u],low[v]);
29         }
30         else if(vis[v])low[u]=min(low[u],dfn[v]);
31     }
32     if(low[u]==dfn[u]){
33         int x;
34         num++;
35         do{
36             x=stack[top--];
37             c[x]=num+n;
38             w[num+n]++;
39             add(num+n,x);
40             vis[x]=0;
41         }while(x!=u);
42     }
43 }
44 int main(){
45     scanf("%d%d%d",&n,&m,&h);
46     for(int i=1;i<=n;i++){
47         scanf("%d",&t[i]);
48     }
49     for(int i=1;i<=m;i++){
50         scanf("%d%d",&a[i],&b[i]);
51         if(t[a[i]]+1==t[b[i]]||(t[a[i]]==h-1&&t[b[i]]==0))add(a[i],b[i]);
52         if(t[b[i]]+1==t[a[i]]||(t[b[i]]==h-1&&t[a[i]]==0))add(b[i],a[i]);
53     }
54     for(int i=1;i<=n;i++){
55         if(dfn[i]==0)Tarjan(i);
56     }
57     for(int i=1;i<=m;i++){
58         if(c[a[i]]==c[b[i]])continue;
59         if(t[a[i]]+1==t[b[i]]||(t[a[i]]==h-1&&t[b[i]]==0))deg[c[a[i]]]++;
60         if(t[b[i]]+1==t[a[i]]||(t[b[i]]==h-1&&t[a[i]]==0))deg[c[b[i]]]++;
61     }
62     int minn=9999999;
63     for(int i=n+1;i<=n+num;i++){
64         if(deg[i]==0&&minn>w[i]){
65             minn=w[i];
66             ans=i;
67         }
68     }
69     printf("%d
",w[ans]);
70     for(int i=head[ans];i;i=e[i].nxt){
71         int v=e[i].to;
72         printf("%d ",v);
73     } 
74     return 0;
75 } 
View Code
原文地址:https://www.cnblogs.com/Xu-daxia/p/9385811.html