Luogu4700 CEOI2011 Traffic Tarjan、搜索
题意:给出平面上$N$个点,它们一定在左下角为$(0,0)$,右上角为$(A,B)$的一个矩形内的整点上(包括边界),而且会给出$M$条呈直线的边,其中有有向边也有无向边,保证任意两条边不会在非顶点处相交。现在我们定义横坐标为$0$的点为在西边的点,横坐标为$A$的点为在东边的点,现在请求出每一个在西边的点都能通过给出的边到达多少在东边的点。$N \leq 3 \times 10^5 , M \leq 9 \times 10^5 , 1 \leq A , B , \text{点的坐标} \leq 10^9$
其实还是挺考验思维的
首先一看到这道题:诶这不是裸的$tarjan$套记搜吗,然后打完发现会算重很多东西,样例都过不了qwq。
其实题目中有一句话十分隐蔽:保证任意两条边不会在非顶点处相交,这会给我们什么信息呢?
直接讲结论:除了无法到达的点,每一个西边的能够到达的东边的点都会对应纵坐标的一段区间,也就是说一定是从上往下一段连续的点,而如果其中有无法到达的点,那么一定是所有的西边的点都无法到达它。这个结论与引水入城的思想十分类似。所以我们可以先缩点,然后在剩下的$DAG$上进行记忆化搜索,把每一个西边的点能够到达的东边的点对应的区间记录下来(显然这个是很好记录的,只要记录两个端点即可),然后再去检索是否有无法到达且在这一段区间内的东边的点,将其扣除即可。
关于下面的代码,思想与上面一致,只是为了易于统计答案,将所有的边都取反,然后统计每一个东边的点能够影响的西边的点的区间,然后用前缀和获得每一个西边节点的答案,最后去看每一个西边的点对应的强连通分量是否被到达过(没有就表示没有东边的点可以到达它,自然答案就是$0$)
#include<bits/stdc++.h>
using namespace std;
inline int read(){
;
;
char c = getchar();
while(c != EOF && !isdigit(c)){
if(c == '-')
f = ;
c = getchar();
}
while(c != EOF && isdigit(c)){
a = (a << ) + (a << ) + (c ^ ');
c = getchar();
}
return f ? -a : a;
}
;
struct Edge{
int end , upEd;
}Ed[MAXN * ] , newEd[MAXN * ];
struct node{
int y , ind;
}now[MAXN];
][MAXN] , ind[MAXN] , num[MAXN] , s[MAXN] , dfn[MAXN] , low[MAXN];
int N , M , A , B , cntEd , cntNode , ts , headS , cntNewEd , cntSCC;
bool vis[MAXN] , ins[MAXN] , ine[MAXN];
queue < int > q;
inline void addEd(Edge* Ed , int* head , int& cntEd , int a , int b){
Ed[++cntEd].end = b;
Ed[cntEd].upEd = head[a];
head[a] = cntEd;
}
void tarjan(int x){
dfn[x] = low[x] = ++ts;
vis[x] = ins[x] = ;
s[++headS] = x;
for(int i = head[x] ; i ; i = Ed[i].upEd){
if(!vis[Ed[i].end])
tarjan(Ed[i].end);
else
if(!ins[Ed[i].end])
continue;
low[x] = min(low[Ed[i].end] , low[x]);
}
if(dfn[x] == low[x]){
cntSCC++;
do{
int t = s[headS];
in[t] = cntSCC;
ins[t] = ;
if(ind[t]){
len[][cntSCC] = min(len[][cntSCC] , ind[t]);
len[][cntSCC] = max(len[][cntSCC] , ind[t]);
}
}while(s[headS--] != x);
}
}
void create(){
; i <= N ; i++)
for(int j = head[i] ; j ; j = Ed[j].upEd)
if(in[Ed[j].end] != in[i])
addEd(newEd , newHead , cntNewEd , in[i] , in[Ed[j].end]);
}
void dfs(int x){
if(vis[x])
return;
vis[x] = ;
for(int i = newHead[x] ; i ; i = newEd[i].upEd){
dfs(newEd[i].end);
len[][x] = min(len[][x] , len[][newEd[i].end]);
len[][x] = max(len[][x] , len[][newEd[i].end]);
}
}
bool operator <(node a , node b){
return a.y > b.y;
}
int main(){
#ifdef LG
freopen("4700.in" , "r" , stdin);
freopen("4700.out" , "w" , stdout);
#endif
memset(len[] , ]));
N = read();
M = read();
A = read();
B = read();
; i <= N ; i++){
int x = read() , y = read();
if(x == A)
ine[i] = ;
else
if(!x){
now[++cntNode].y = y;
now[cntNode].ind = i;
}
}
; i <= M ; i++){
int a = read() , b = read() , c = read();
addEd(Ed , head , cntEd , b , a);
)
addEd(Ed , head , cntEd , a , b);
}
sort(now + , now + cntNode + );
; i <= cntNode ; i++)
ind[now[i].ind] = i;
; i <= N ; i++)
if(!vis[i])
tarjan(i);
memset(vis , , sizeof(vis));
create();
; i <= N ; i++)
if(ine[i]){
dfs(in[i]);
][][in[i]]){
num[len[][in[i]]]++;
num[len[][]--;
}
}
; i <= cntNode ; i++)
num[i] += num[i - ];
; i <= cntNode ; i++)
cout << (!vis[ : num[i]) << endl;
;
}
Luogu4700 CEOI2011 Traffic Tarjan、搜索的更多相关文章
- [Ceoi2011]Traffic
#2387. [Ceoi2011]Traffic Online Judge:Bzoj-2387,Luogu-4700 Label:Yy,Tarjan缩点,dfs 题目描述 格丁尼亚的中心位于Kacza ...
- bzoj 2387: [Ceoi2011]Traffic
bzoj 2387: [Ceoi2011]Traffic 题目描述 The center of Gdynia is located on an island in the middle of the ...
- 152 - - G Traffic Light 搜索(The 18th Zhejiang University Programming Contest Sponsored by TuSimple )
http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5738 题意 给你一个map 每个格子里有一个红绿灯,用0,1表示 ...
- tarjan - tarjan的几种用法
前言 tarjan是一种神奇的算法, 它可以在线性时间内求强联通分量/缩点/LCA/割点/割边/... 但由于博主咸鱼,暂时掌握不了这么多, 先讲讲其中最简单的一些. 概述 tarjan是以DFS为基 ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- UVA-315 无向图求割点个数
题意抽象: 给定一个无向图,输出割点个数. 割点定义:删除该点后,原图变为多个连通块. 考虑一下怎么利用tarjan判定割点: 对于点u和他相连的当时还未搜到的点v,dfs后如果DFN[u]<= ...
- Codeforces Round #377 (Div. 2) F - Tourist Reform
前言:关于如何求双连通分量,我们可以在tarjan搜索时标记下所有桥的位置(双连通分量(可以认为是没有桥的无向图图)即可通过删去所有桥得到),那么怎么找桥呢,对于每一条搜索到的边u->x,如果l ...
- ASO--简单了解
ASO是“应用商店优化”的简称.ASO(App Search Optimization)就是提升你APP在各类APP应用商店/市场排行榜和搜索结果排名的过程. 类似普通网站针对搜索引擎的优化,即SEO ...
- luogu3953 [NOIp2017]逛公园 (tarjan+dijkstra+记忆化搜索)
先跑一边dijkstra算出从1到i的最短距离dis[i] 然后建反向边 从n开始记忆化搜索,(p,k)表示1到p的距离=dis[p]+k的方案数 答案就是$\sum\limits_{i=0}^{k} ...
随机推荐
- python之MRO和C3算法
python2类和python3类的区别pyhon2中才分新式类与经典类,python3中统一都是新式类Python 2.x中默认都是经典类,只有显式继承了object才是新式类python 3.x中 ...
- docker 搭建maven 私服
# 搜索镜像 docker search nexus; #拉取nexus镜像docker pull sonatype/nexus; #运行 -id 创建守护式容器--privileged=true 授 ...
- python 类函数,实例函数,静态函数
一.实现方法 class Function(object): # 在类定义中定义变量 cls_variable = "class varibale" def __init__(se ...
- Ubuntu 16.04.4 LTS + Ambari 2.6.1.5 + HDP 2.6.4.0 安装部署
服务器 主机名 master slave1 slave2 slave3 IP 192.168.1.40 192.168.1.41 192.168.1.42 192.168.1.43 离线包服务器: 1 ...
- Linux 学习笔记之超详细基础linux命令 Part 9
Linux学习笔记之超详细基础linux命令 by:授客 QQ:1033553122 ---------------------------------接Part 8----------------- ...
- loadrunner 场景设计-目标场景设计
场景设计-目标场景设计 by:授客 QQ:1033553122 A. 概述 Goals Types for Goal-Oriented Scenarios 在以目标为向导的场景中,定义你想实现的测 ...
- 解决ArrayList线程不安全
前些天做项目时,程序出现意外的问题,经后来分析是使用ArrayList这个线程不安全的方法导致 解决这个问题通常有两种方法(个人认为) 一:使用synchronized关键字,这个大家应该都很熟悉了, ...
- Fiddler抓包使用教程-QuickExec
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/73468287 本文出自[赵彦军的博客] 在 Fiddler 中自带了一个 Quic ...
- JdbcTemplate学习笔记(更新插入删除等)
1.使用JdbcTemplate的execute()方法执行SQL语句 jdbcTemplate.execute("CREATE TABLE USER (user_id integer, n ...
- Websocket通信过程
1. 客户端与服务器建立连接 2. 客户端通过session向服务器发送消息 3. 服务器接收客户端的消息,调用服务器端的onMessage()方法包装.生成消息内容(新的消息包括客户端ID) 4. ...