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} ...
随机推荐
- svg简介与使用
什么是svg SVG是"Scalable Vector Graphics"的简称.中文可以理解成"可缩放矢量图形". 可缩放矢量图形是基于可扩展标记语言(标准通 ...
- 我的第一个个人博客网站 -> wizzie.top
从去年下半年实习结束,到找到第一个属于自己的工作,我就开始着手搭建自己的网站. 使用阿里云学生服务器,域名,备案解析后,开始设计网站结构和页面布局. 因为临近毕业,网站真的是写的页面怎么多怎么写,所以 ...
- 分享一下我研究SQLSERVER以来收集的笔记
分享一下我研究SQLSERVER以来收集的笔记 前言 为什麽分享??因为像现在网上很多人攻城师那样,转行去卖水果,卖早餐,总有一日我也会离开这个行业的 由于本人不是在大公司上班工资很低,我希望有一天存 ...
- android ninja【转】
Android7.0 Ninja编译原理 引言 使在Android N的系统上,初次使用了Ninja的编译系统.对于Ninja,最初的印象是用在了Chromium open source code的编 ...
- Tell Me About Yourself Example 1
Tell Me About Yourself Employers ask this question because they want to know you have the relevant e ...
- jQuery.form 的最新版本是 3.14
http://www.oschina.net/news/32628/jquery-form-3-14 有日子没跟进 jQuery.form 插件了,该插件已经从 2.xx 更新到 3.xx 了,目前最 ...
- c++11の的左值、右值以及move,foward
左值和右值的定义 在C++中,可以放到赋值操作符=左边的是左值,可以放到赋值操作符右边的是右值.有些变量既可以当左值又可以当右值.进一步来讲,左值为Lvalue,其实L代表Location,表示在内存 ...
- swift的类型描述符
Metatype Types A concrete or existential metatype in SIL must describe its representation. This can ...
- web socket RFC6455 frame 打包、解包
#ifndef __APP_WEBSOCKET_FRAME_H__ #define __APP_WEBSOCKET_FRAME_H__ #include "memory.hpp" ...
- MDC的使用(Mapped Diagnostic Context)的使用
通常我们可能会有大量的任务需要提交提交到线程池执行,但是此时如果不对日志添加唯一标识进行区分的话回到错乱一坨无法进行查看.因此可以对每一天日志添加唯一的标识,例如使用userid作为日志的唯一标志.这 ...