Codeforces 949C(Data Center Maintenance,Tarjan缩点)
难度系数:1900 graphs
题意:有 n 个银行,m 个客户,每个客户都把自己的资料放在 2 个银行,一天总共有 h 小时,每个银行每天都要维护一小时,这一小时内银行无法工作,但是这一小时客户仍然可以在另一个银行提取资料,于是客户就可以一天 h 小时随时提取资料。现在要选择 k 个银行进行实验,每个进行实验的银行,它每天的维护时间都推迟一小时,如果原来的维护时间是 h−1 时,进行实验后银行的维护时间就为 0 时。问最少选择几个银行(至少一个)进行实验,才能仍然保证每一个客户随时都能提取到资料。
输入:第一行为 3 个整数n,m,h (2≤n≤105,1≤m≤1e5,2≤h≤1e5),第二行为 nn 个整数 u1,u2,⋯,un (0≤ui<h)表示第 i 个银行一天内需要维护的时间点。接下去 m行每行两个整数 ci,1,ci,2 (1≤ci,1,ci,2≤n),表示第 i 个客户把资料存放在第 ci,1 和第 ci,2 个银行。数据保证最初每一个客户都可以在一天的任意时刻取得资料。
解法:其实想想也能知道转化成图论关系,但是怎么建边呢?我们可以知道如果(p[u]+1)%h==p[v],就能在u和v之间建立一个单向边,add(u,v);同样,如果(p[v]+1)%h==p[u],就能在v和u之间建立一个单向边,add(v,u)。记住建边的时候不要用 else if,因为有一组数据卡的条件是回路只有2个点...既然知道了建边的关系了,那么我们就可以利用Tarjan强联通的缩点方法把它缩成id[i],这个时候统计一下每个id[i]的outdeg有几个;我们寻找答案的方法是:1~n中,outdeg[id[i]]为0,且num[id[i]]最小。那么其实这个问题说到这个地步也算是比较简单了。感觉想想还是挺容易的,就是坑点有点多吧。。。
#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define endl '\n'
#define mem(a,b) memset(a,b,sizeof(a))
#define IO ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
const int INF=0x3f3f3f3f;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int mod=1e9+;
const int maxn=1e5+;
int tot,head[maxn];
struct E{
int to,next;
}edge[maxn<<];
void add(int u,int v){
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot++;
}
int n,m,h,p[maxn],dfn[maxn],low[maxn],vis[maxn],id[maxn],num[maxn],tott,cnt=;
stack<int> s;
void tarjan(int x){
low[x]=dfn[x]=++tott;
s.push(x);vis[x]=;
for(int i=head[x];i!=-;i=edge[i].next){
int v=edge[i].to;
if(!dfn[v]){
tarjan(v);
low[x]=min(low[x],low[v]);
}
else if(vis[v]){
low[x]=min(low[x],dfn[v]);
}
}
if(low[x]==dfn[x]){
cnt++;
while(){
int now=s.top();s.pop();
vis[now]=;
id[now]=cnt;
num[cnt]+=;
if(now==x) break;
}
}
}
int out[maxn];vector<int> G[maxn];
int main(){
cin>>n>>m>>h;mem(head,-);
rep(i,,n) cin>>p[i];
while(m--){
int u,v;cin>>u>>v;
if((p[u]+)%h==p[v]) add(u,v);
if((p[v]+)%h==p[u]) add(v,u);
}
rep(i,,n){
if(!dfn[i]) tarjan(i);
}
for(int i=;i<=n;i++){
for(int j=head[i];j!=-;j=edge[j].next){
if(id[i]!=id[edge[j].to]){
G[id[i]].push_back(id[edge[j].to]);
out[id[i]]+=;
}
}
}
int ans=INF,cur;
for(int i=;i<=cnt;i++){
if(out[i]==){
ans=min(ans,num[i]);
if(num[i]==ans) cur=i;
}
}
vector<int> vec;
for(int i=;i<=n;i++){
if(id[i]==cur){
vec.push_back(i);
}
}
cout<<ans<<endl;
for(int i=;i<vec.size();i++){
cout<<vec[i]<<" ";
}
puts("");
}
Codeforces 949C(Data Center Maintenance,Tarjan缩点)的更多相关文章
- codeforces 949C - Data Center Maintenance【tarjan】
首先转换图论模型,把某个客户一个终端的维修时间(+1)%h之后和另一个终端维修时间一样,这样的两个终端连一条有向边,表示推后一个终端就必须推后另一个 然后tarjan缩点,一个scc里的终端是要一起推 ...
- Codeforces 950E Data Center Maintenance ( 思维 && 强连通分量缩点 )
题意 : 给出 n 个点,每个点有一个维护时间 a[i].m 个条件,每个条件有2个点(x,y)且 a[x] != a[y].选择最少的 k (最少一个)个点,使其值加1后,m个条件仍成立. 分析 : ...
- CF 949C Data Center Maintenance——思路+SCC
题目:http://codeforces.com/contest/949/problem/C 可以想到可能是每组c有连边的可能. 但别直接给c1.c2连边,那样之后会变得很不好做. 可以把一些限制放在 ...
- Codeforces 950E Data Center Maintenance 强连通分量
题目链接 题意 有\(n\)个信息中心,每个信息中心都有自己的维护时间\((0\leq t\lt h)\),在这个时刻里面的信息不能被获得. 每个用户的数据都有两份备份,放在两个相异的信息中心(维护时 ...
- Codeforces 950.E Data Center Maintenance
E. Data Center Maintenance time limit per test 1 second memory limit per test 512 megabytes input st ...
- Codeforces Round #469 (Div. 1) 949C C. Data Center Maintenance (Div. 2 950E)
题 OvO http://codeforces.com/contest/949/problem/C codeforces 949C 950E 解 建图,记原图为 G1,缩点,记缩完点后的新图为G2 缩 ...
- Codeforces Round #469 (Div. 2) E. Data Center Maintenance
tarjan 题意: 有n个数据维护中心,每个在h小时中需要1个小时维护,有m个雇主,他们的中心分别为c1,c2,要求这两个数据中心不能同时维护. 现在要挑出一个数据中心的子集,把他们的维护时间都推后 ...
- codeforce469DIV2——E. Data Center Maintenance
题意: 有n个数据中心,m个客户,每天有h个小时,其中 n,m,h<=100000.每个数据中心i每天都会有一个数据维护的时间0<=u[i]<=h-1,在数据中心维护期间时不可以使用 ...
- Data Center Maintenance CodeForces - 950E
http://codeforces.com/contest/950/problem/E 贴一份板子 #include<cstdio> #include<vector> #inc ...
随机推荐
- python 规范篇 如何合理使用 assert
assert 的合理使用,可以增加代码的健壮度,同时也方便了程序出错时开发人员的定位排查. 什么是 assert? Python 的 assert 语句,可以说是一个 debug 的好工具,主要用于测 ...
- sort()实现排序的原理
很多人都只知道sort()是通过快速排序实现,但它并不只是简单的快排:首先它对普通的快速排序进行了优化:此外,它还结合了插入 排序和堆排序.系统根据数据形式和数据量,来选择合适的排序方法,这并不是说每 ...
- 批量查询PDF文本并导出结果的小工具
效果: 批量查询指定关键字 & 指定目录下PDF文件中的文本,并导出文件路径和关键字所在文本行. 下载: 链接: https://pan.baidu.com/s/1sK2OMMgGX26l7P ...
- 2019-2020-1 20199310《Linux内核原理与分析》第四周作业
1.问题描述 在前面的文章中,已经接触过一些Linux内核的知识,本文将进一步从Linux内核源代码的目录结构入手,在Oracle VM VirtualBox的Linux环境中构造一个简单的操作系统M ...
- SpringCloud入门(十一):Sleuth 与 Zipkin分布式链路跟踪
现今业界分布式服务跟踪的理论基础主要来自于 Google 的一篇论文<Dapper, a Large-Scale Distributed Systems Tracing Infrastructu ...
- 关于bash shell的理解
Bash Shell 基本特性 1.命令选项参数的补全 补全选项,需要安装 bash-completion yum install -y bash-completion 2.快捷键 Ctrl + a ...
- 【Linux常见命令】tail命令
tail - output the last part of files tail 命令可用于查看文件的内容,有一个常用的参数 -f 常用于查阅正在改变的日志文件. tail -f filename ...
- JavaWEB开发时FCKeditor类似office界面的ajax框架,加入后就能做界面类似office,能进行简单的文本编辑操作+配置手册...
2019独角兽企业重金招聘Python工程师标准>>> FCKeditor是一款功能强大的开源在线文本编辑器(DHTML editor),它使你在web上可以使用类似微软Word 的 ...
- 数学--数论--HDU - 6124 Euler theorem (打表找规律)
HazelFan is given two positive integers a,b, and he wants to calculate amodb. But now he forgets the ...
- YUM 安装lnmy
yum -y install nginx systemctl start nginx.service yum -y install php php-fpm php-mysql php-gd libjp ...