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\n",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 } 

原文地址:https://www.cnblogs.com/Xu-daxia/p/9385811.html

时间: 2024-10-25 18:04:57

CF949C Data Center Maintenance(建图+强联通分量)的相关文章

CF949C Data Center Maintenance Tarjan找强连通分量

题意 给你\(n\)个点,每个点有一个权值\(a_x\),有\(m\)个限制条件形如\(a_x≠a_y\),现在要求你选出\(k(k>0)\)个点使其权值在模\(h\)意义下加\(1\),问最少选多少个点能让限制条件继续满足. \(Tarjan\)求强连通分量模板题 发现对于每个限制条件,如果\(a_x+1=a_y(mod\ h)\) 那么可以给\(y\)向\(x\)连一条有向边 那么最后缩点后找到入度为\(0\)的最小\(scc\)大小即可 Codes #include <cstdio>

[CF949C]Data Center Maintenance

题目大意:$n$个点,每个点有一个值$w_i$.$m$个条件,每个条件给出$x,y$,要求$w_x\not =w_y$.选择最少的点,使其值加$1$后,所有条件成立(数据保证有解). 题解:对于每个条件,若$(w_x+1)\bmod h=w_y$,连上$x->y$:若$(w_y+1)\bmod h=w_x$,连上$y->x$.一条边的含义是,若起点加一,终点也要加一.缩点,强连通分量内的点要一起加.发现答案就是找最小的没有出边的点 卡点:无 C++ Code: #include <cst

【POJ1236】Network of Schools 强联通分量缩点(本文kosaraju)

/*不要说这题多水之类的--我只是想记一下kosaraju这种屌炸天的dfs序延伸算法(说不定能加到我的ygylca里面)*/ 题意神马的都不说了,好吧,就是给你个图,n个点,然后n行每行都描述该点的出边,图建完了,然后缩点,然后问多少个点没有入度,再问需要加几条边可以让图变强联通图. 强联通图:图中任意两点之间都能互相到达(前提得是有向图你懂的,无向图就有点乱了,根本不要算法了,暴搜就好了) 强联通分量:同强联通图,不过是图中一部分. 缩点,把一个分量视为一个点,缩起来(一般不缩,都是记录每个

codevs 2822 爱在心中 tarjan(强联通分量)

2822 爱在心中 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description “每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动.爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our Home.” 在爱的国度里有N个人,在他们的心中都有着一个爱的名单,上面记载着他所爱的人(不会出现自爱的情况).爱是具有传递性的,即如果A爱B,B爱C,则A也爱C.如果有这样一部分人,他们彼此都相爱,则他们就超越了一

有向图的强联通分量

最近学了有向图的强联通分量.有kosaraju算法,不过写着比tarjin麻烦.所以就只记录tarjin算法. 跟求无向图的双连通分量很相似,先贴代码. 1 void dfs(int u){ 2 dfn[u]=low[u]=++clk;//dfn序 3 stk[top++]=u;//压入栈内 4 for(int i=head[u];i;i=edge[i].nxt){ 5 int t=edge[i].to; 6 if(dfn[t]==0){//如果下一个节点是没有访问过的 7 dfs(t); 8

POJ 2186 Popular cows(Kosaraju+强联通分量模板)

题目链接:http://poj.org/problem?id=2186 题目大意:给定N头牛和M个有序对(A,B),(A,B)表示A牛认为B牛是红人,该关系具有传递性,如果牛A认为牛B是红人,牛B认为牛C是红人,那么牛A也认为牛C是红人.求被其他所有牛认为是红牛的牛的总数. 解题思路:把所有牛看成顶点,把有序对(A,B)看成从A到B的有向边,那么题目就变成了求所有顶点都可到达的顶点的总数.我们可以得到一个结论,如果一个强连通分量里有一头牛被认为是红人,那么该强联通分量里的所有牛都是红人,这显然是

Light OJ 1034 - Hit the Light Switches(强联通分量)

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1034 题目大意:有n盏灯,有m个关系, 关系a,b表示如果a灯开关打开那么b灯也会亮起来, 现在求至少需要打开多少开关使所有灯都亮. 题目思路:先由强联通分量缩点, 得到DAG图, 然后根据DAG图,求出有多少入度为0的点, 即为所求. 代码如下: #include<bits/stdc++.h> using namespace std; const int N = 1000

[CF #236 (Div. 2) E] Strictly Positive Matrix(强联通分量)

题目:http://codeforces.com/contest/402/problem/E 题意:给你一个矩阵a,判断是否存在k,使得a^k这个矩阵全部元素都大于0 分析:把矩阵当作01矩阵,超过1的都当作1,那么a矩阵可表示一个有向图的走一次的连通性,则a^k表示有向图走K次的连通性.既然要求最后都没0,即走了K次后,每个点都能互通,这也说明这个图必然是只有一个强联通分量.于是判断k的存在有无,也就是判断a矩阵表示的有向图是不是只有一个强联通分量.

爆零后的感受外加一道强联通分量HDU 4635的题解

今天又爆零了,又是又,怎么又是又,爆零爆多了,又也就经常挂嘴边了,看到这句话,你一定很想说一句"",弱菜被骂傻,也很正常啦. 如果你不开心,可以考虑往下看. 翻到E(HDU 4635 Strongly connected)题,这么短的题目,肯定要先看啦.然后D(LightOJ 1229),然后C(ZOJ 2243),然后F(HDU 4711),然后B(CodeForces 385D),然后看A(HDU 3889)好吧,我承认,A题看了一眼就不看了,B题一看是线段什么有点几何的味道就果断