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} ...
随机推荐
- Java 开源博客 Solo 1.8.0 发布 - 改进文件上传
本次发布主要是更新了编辑器,使其更好地支持文件上传.(1.8.0 版本变更记录请看这里) 我们的 Markdown 编辑器: 另外,我们对 HTTPS 的支持也更完善了,欢迎大家试用! 简介 Solo ...
- 从零自学Java-10.充分利用现有对象
1.超类和子类的设计:2.建立继承层次:3.覆盖方法. 程序StringLister:使用数组列表和特殊的for循环将一系列字符串按字母顺序显示到屏幕上.这些字符串来自一个数组和命令行参数 packa ...
- LeetCode题解之Balanced Binary Tree
1.题目描述 2.问题分析 DFS. 3.代码 bool isBalanced(TreeNode* root) { if (root == NULL) return true; && ...
- 盐城 - 开设IT公司的好地方
盐城:位于江苏省北部,这一好像只能算三线的城市,不久前当选为“国家中心城市”.在全国仅有的50城市中名列34.它可成为发展IT产业的好地方. (1)人才济济.从这里走出去的高级人才数不胜数,留在这里的 ...
- solr-query
解释: 1.query:获取全部数据的SQL 2.deltaImportQuery:获取增量数据时使用的SQL 3.deltaQuery:获取pk的SQL 4.parentDeltaQuery:获取父 ...
- 洗礼灵魂,修炼python(52)--爬虫篇—【转载】爬虫工具列表
与爬虫相关的常用模块列表. 原文出处:传送门链接 网络 通用 urllib -网络库(stdlib). requests -网络库. grab – 网络库(基于pycurl). pycurl – 网络 ...
- python第六十八天--第十二周作业
主题: 需求: 用户角色,讲师\学员, 用户登陆后根据角色不同,能做的事情不同,分别如下讲师视图 管理班级,可创建班级,根据学员qq号把学员加入班级 可创建指定班级的上课纪录,注意一节上课纪录对应多条 ...
- Android ListView在增加HeaderView之后使用getLocationInWindow和getLocationOnScreen获得值不正确的解决方法
近日遇到一个很恶心的问题,把解决方法放到空间里来分享给大家: 问题发生的条件: 1)ListView 控件中使用addHeaderView,为其添加了一个header view.(基本常识:heade ...
- Linux 内存池【转】
内存池(Memery Pool)技术是在真正使用内存之前,先申请分配一定数量的.大小相等(一般情况下)的内存块留作备用.当有新的内存需求时,就从内存池中分出一部分内存块,若内存块不够再继续申请新的内存 ...
- 通过SQL直接插入、修改ArcGIS SDE空间表中的数据
基于Arcgis Server 10.1 +Oracle 11g环境测试 ArcGIS SDE ? 1 2 INSERT INTO CAMERA_INFO(OBJECTID,ID,SHAPE) ...