#2387. [Ceoi2011]Traffic

Online Judge:Bzoj-2387,Luogu-4700

Label:Yy,Tarjan缩点,dfs

题目描述

格丁尼亚的中心位于Kacza河中的一座岛屿。每天清晨,成千上万辆汽车通过岛屿从西岸的住宅区(由桥连接岛的西部)到东岸的工业区(由桥连接岛的东部)。该岛类似于矩形,它的边平行于主方向。故可将它看作是笛卡尔坐标系中的一个A*B的矩形,它的对角分别为(0, 0)和(A, B)。岛上有n个交通节点,编号为1…n(junction, 此处可理解为广义的路口),第i个节点坐标为(xi, yi)。如果一个节点的坐标为(0, y),它就位于岛的西岸。类似的,坐标为(A, y)的节点位于岛的东岸。各个节点由街道连接,每条街道用线段连接两个节点。街道有单向行驶或双向行驶之分。除端点外任意两条街道都没有公共点。也没有桥梁或者隧道。你不能对道路网络形状做任何其他假设。沿河岸的街道或节点可能没有入口或者出口街道。由于交通堵塞日趋严重,市长聘请你测试岛上当前的道路网是否足够。

要求你写一个程序确定从岛的西岸的每个节点能够到达东岸的多少个节点。

Luogu翻译d题面

输入格式

第1行包含4个整数n, m, A, B(\(1≤n≤300000, 0≤m≤900000,1≤A,B≤10^9\)),

分别表示格丁尼亚市中心的节点数,街道数和岛屿的尺寸。

接下来的n行,每行包含两个整数\(x_i\),\(y_i\) (\(0≤xi≤A,0≤yi≤B\)),表示第i个节点的坐标。任意两个节点的坐标都不相同。

再往下的m行表示街道,每条街道用3个整数\(c_i, d_i, k_i(1≤c_i, d_i≤n, c_i≠d_i, k_i∈{1,2})\),表示节点\(c_i、d_i\)有街道连接。如果\(k_i=1\),表示从\(c_i\)到\(d_i\)的街道是单向的,否则,这条街道可以双向行驶。每个无序对{\(c_i, d_i\)}最多出现1次。

你可以假设西岸节点中至少有1个能够到达东岸的一些节点。

输出格式

为每个西岸节点输出1行,包括从这个节点出发能够到达东岸的节点数目

请按照y从大到小的顺序输出所有点对应的答案。

样例

输入

5 3 1 3
0 0
0 1
0 2
1 0
1 1
1 4 1
1 5 2
3 5 2

输出

2
0
2

题解:

首先对于同一个强连通分量里的点来说,他们能到达的东岸的点的个数是相同的。所以考虑Tarjan缩点,然后再重新建图,那么经过缩点后重建的图就不存在双向边了。

接下来怎么搞呢?

1.一种超好想然而会爆WA的\(O(N)\)思路:

对于每个节点i记录Dp[i],表示从i开始走能到达的东岸的点的个数。然后就是对整个图进行记忆化搜索。

\[Dp[x]=∑_{son∈x} Dp[son]
\]

但是这个方法存在一个问题,由于我们不一定从树根开始搜起,所以会出现重复计数的问题,例:如果x的两个儿子son1,son2都能到达某个东岸的点o,那么o就会被重复计数,所以答案是错误的。

2.一种超好想然而会爆T的\(O(N^2)\)思路:

就是缩完点之后,从每个西岸的点开始bfs、dfs都可,加上蜜汁优化卡常似乎可以跑过好多点。


AC做法:

第二种的\(O(N^2)\)肯定不可取,考虑如何修改第一种会WA的做法。

注意题面中一个非常非常重要的提示:除端点外任意两条街道都没有公共点

结合下图,图中的每一个点都代表一个强连通分量。

我们发现,对于西岸的任意一点W来说,假设W所能访问到东岸的所有点中,高度最高的为ma,高度最低的为mi,则东岸中高度处于\([mi,ma]\)之间的点E,都可以被W访问到。

当然还有一个前提条件,就是E必须是能被西岸至少一个点访问到的,比如下图中东岸的C点,它就不能被西岸中至少一个点访问到,所以把像C这样的——在东岸却不能被至少一个在西岸的点,从东岸中剔除——因为他存不存在对答案没有影响,如何剔除呢,一个\(O(N)\)的dfs预处理就可以完成。

回过头看,当满足这个前提条件时,上面的发现必然成立,先来看看下图,比如对于点2来说,它对应的ma是B,对应的mi是D,那么高度处于B~D之间的必然也能被2访问到——(C由于不符合上面那个前提条件已经从东岸中剔除了)。

这个发现的正确性显而易见,如果存在某个未剔除的东岸的点它不满足条件,那么图中就会有两条线相交,而这不符合题目给定的那个提示,所以我们就可以根据这个性质来做了。

大致思路

  1. 剔除不能被西岸的点访问到的东岸的点,这里从西岸的每一个点开始dfs一遍,vis数组标记一下是否到过;
  2. 对东岸中剩余的点按照高度(纵坐标)从高到低排序——反一下也没关系;
  3. Tarjan缩点,跑的时候注意,如果加入当前强连通分量的点是东岸的点的话更新一下该强连通分量的ma,mi值;
  4. 重新建图,搜索整张图——(把图当作一棵普通的树,因为从左往右的边其实相当于没有),然后通过递归更新每个节点的ma,mi值。
  5. 排序一下西岸的每个点,依次输出,对于某点x来说,它的答案为\(ma[i]-mi[i]+1\)。

综上,由于存在排序,上述做法的时间复杂度为\(O(NlogN)\)。

当然这道题如果不缩点的话也可以,做法类似,只要通过题目读出隐藏性质转化问题就可以随便做了。

code☇

#include<bits/stdc++.h>
using namespace std;
#define debug(x) cout<<"####"<<x<<endl;
typedef pair<int,int> pii;
const int N=300010;
inline int read(){
int x=0;char c=getchar();
while(c<'0'||c>'9')c=getchar();
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x;
}
pii p[N];
int A,B,n,m,idx,id[N];
vector<int>lp,rp,e[N],g[N];
bool vis[N];//vis:从西岸出发能否到达i
int pos[N],ma[N],mi[N];//ma/mi:某强连通分量能到达东岸的最高、低点
int dfn[N],low[N],ins[N],tot;
stack<int>s;
void tarjan(int x){
dfn[x]=low[x]=++tot;
s.push(x);ins[x]=1;
for(int i=0;i<e[x].size();i++){
int y=e[x][i];
if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
}
else if(ins[y])low[x]=min(low[x],dfn[y]);
}
int k;
if(low[x]==dfn[x]){
idx++;
do{
k=s.top();s.pop();
ins[k]=0,id[k]=idx;
if(p[k].first==A){
ma[idx]=max(ma[idx],pos[k]);
mi[idx]=min(mi[idx],pos[k]);
}
}while(x!=k);
}
}
void search(int x){
vis[x]=1;
for(int i=0;i<g[x].size();i++){
int y=g[x][i];
if(!vis[y])search(y);
ma[x]=max(ma[x],ma[y]);
mi[x]=min(mi[x],mi[y]);
}
}
void dfs(int x){
vis[x]=1;
for(int i=0;i<e[x].size();i++){
if(!vis[e[x][i]])dfs(e[x][i]);
}
}
inline bool cmp(int a,int b){return p[a].second>p[b].second;}
int main(){
memset(mi,0x3f,sizeof(mi)); n=read(),m=read(),A=read(),B=read();
for(int i=1;i<=n;i++){
int x=read(),y=read();
if(x==0)lp.push_back(i);
if(x==A)rp.push_back(i);
p[i]=make_pair(x,y);
} for(int i=1;i<=m;i++){
int u=read(),v=read();
e[u].push_back(v);
if(read()==2)e[v].push_back(u);
} for(int i=0;i<lp.size();i++)dfs(lp[i]); sort(rp.begin(),rp.end(),cmp);
int eastnum=0;
for(int i=0;i<rp.size();i++){
int y=rp[i];
if(vis[y])pos[y]=++eastnum;
} for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i); for(int i=1;i<=n;i++)for(int j=0;j<e[i].size();j++){
int y=e[i][j];
if(id[i]!=id[y]){
g[id[i]].push_back(id[y]);
}
}
memset(vis,0,sizeof(vis));
for(int i=1;i<=idx;i++)search(i); sort(lp.begin(),lp.end(),cmp);
for(int i=0;i<lp.size();i++){
int x=id[lp[i]];
printf("%d\n",max(0,ma[x]-mi[x]+1));
}
}

[Ceoi2011]Traffic的更多相关文章

  1. bzoj 2387: [Ceoi2011]Traffic

    bzoj 2387: [Ceoi2011]Traffic 题目描述 The center of Gdynia is located on an island in the middle of the ...

  2. Luogu4700 CEOI2011 Traffic Tarjan、搜索

    传送门 题意:给出平面上$N$个点,它们一定在左下角为$(0,0)$,右上角为$(A,B)$的一个矩形内的整点上(包括边界),而且会给出$M$条呈直线的边,其中有有向边也有无向边,保证任意两条边不会在 ...

  3. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  4. Linux下按程序查实时流量 network traffic

    实然看到下载速度多达几M/s,但实际上并没有什么占用带宽的进程. 相查看每个程序占用的网络流量, 但系统自带的 System Monitor 只能查看全局的流量, 不能具体看某个程序的...... k ...

  5. Windows Azure Traffic Manager (5) Traffic Manager Overview

    <Windows Azure Platform 系列文章目录> 笔者默默地看了一下之前写的Traffic Manager内容,已经差不多是3年前的文章了.现在Azure Traffic M ...

  6. Windows Azure Traffic Manager (6) 使用Traffic Manager,实现本地应用+云端应用的高可用

    <Windows Azure Platform 系列文章目录> 注意:本文介绍的是使用国内由世纪互联运维的Azure China服务. 以前的Traffic Manager,背后的Serv ...

  7. 流量工程 traffic engineering (TE)

    什么是流量工程 流量工程是指根据各种数据业务流量的特性选取传输路径的处理过程.流量工程用于平衡网络中的不同交换机.路由器以及链路之间的负载. [编辑] 流量工程的内容 流量工程在复杂的网络环境中,控制 ...

  8. snmp switch traffic交换机带宽

    上代码 <?php function getstr1($strall,$str1,$str2,$html_charset='utf-8'){ $i1=mb_strpos($strall,$str ...

  9. 每日英语:The Secret About Online Ad Traffic: One-Third Is Bogus

    Billions of dollars are flowing into online advertising. But marketers also are confronting an uncom ...

随机推荐

  1. Windows中的"簇"和Linux中的"块"是对应的

    扇区是对硬盘而言,块是对文件系统而言. 簇”又称为“分配单元” ,文件系统是操作系统与驱动器之间的接口,当操作系统请求从硬盘里读取一个文件时,会请求相应的文件系统(FAT 16/32/NTFS)打开文 ...

  2. [转]SpringMVC框架入门配置 IDEA下搭建Maven项目

    初衷:本人初学SpringMVC的时候遇到各种稀奇古怪的问题,网上各种技术论坛上的帖子又参差不齐,难以一步到位达到配置好的效果,这里我将我配置的总结写到这里供大家初学SpringMVC的同僚们共同学习 ...

  3. 在vue项目引入阿里巴巴矢量图标

    1.在阿里矢量图标库将想要的图标加入购物车,然后在购物车中将图标添加到项目: 2.到我的项目中,将图标下载到本地 3.在vue项目的assets文件夹下新建一个iconfont文件夹(名字自定义),将 ...

  4. C++ 贪吃蛇二维

    #include <iostream> #include <conio.h> #include <windows.h> #include <time.h> ...

  5. kubernetes istio之流量管理

    1.部署 Bookinfo 应用 要在 Istio 中运行这一应用,无需对应用自身做出任何改变.我们只要简单的在 Istio 环境中对服务进行配置和运行,具体一点说就是把 Envoy sidecar ...

  6. kubernetes配置(kubeconfig)对多集群的访问

    配置对多集群的访问 本文展示如何使用配置文件来配置对多个集群的访问. 在将集群.用户和上下文定义在一个或多个配置文件中之后,用户可以使用 kubectl config use-context 命令快速 ...

  7. C++访问sqlite3的初体验

    Sqlite确实是一个比较好的本地数据库,从接触它的时候就喜欢上了它,它可以在很多情况下简化应用.不过以前都是在Java里面使用,或者Linux C下使用的,现在有个项目(C++)可能我会用到sqli ...

  8. vue框架介绍

    vue框架介绍 一.vue 概念 vue 是一种开发用户界面的渐进式开发框架.渐进式指的是:你可以将vue作为一部分嵌入到web应用中,带来丰富的交互体验 二.vue特点及常见开发中的高级功能 1.解 ...

  9. 如何在VUE项目中使用SCSS

    首先要了解什么是CSS 预处理器? SCSS是一种CSS预处理语言 定义了一种新的专门的编程语言,编译后形成正常的css文件,为css增加一些编程特性,无需考虑浏览器的兼容性(完全兼容css3),让c ...

  10. Spring - JUnit整合测试

    1.导包:test.jar - (依赖 aop.jar) 2.使用@RunWith注解创建spring容器 - @RunWith(SpringJUnit4ClassRunner.class) 3.使用 ...