jzoj3577 [CEOI2011]Traffic 强连通分量缩点
2017-12-16 16:27
381 查看
Description
Gdynia 的中心坐落于Kacza 河中游的一个岛屿上。每天早晨,成千辆小车从河流的西岸的住宅区出发穿过岛屿(使用连接岛西路口的桥梁)到达东岸的工业区(使用连接岛东路口的桥梁)。这个岛屿酷似一个边平行于坐标轴的矩形。因此,我们视他为一个笛卡尔坐标系上的A*B的矩形,对角的坐标为(0,0) 和(A,B)。
在这个岛屿上,有n 个路口从1 到n 编号。路口i 位于坐标(xi; yi)。如果一个路口坐标类似于(0,y),那么它在岛西。类似的,坐标形于(A,y) 的路口坐落在岛东。路口通过街道连接起来。每一条街道是一条连接两个路口的线段。街道可以是双向或者单向的。没有两条街道有公共点(除了作为线段端点的路口)。岛上没有桥或者地道。其他的道路网络形状是不被认可的。特别的是,街道可以与岛屿的边缘重合,或者存在没有连接街道的路口。
因为交通密度不断增长,所以市长雇佣你去检查现在的道路网络是否足够。他要求你写一个程序,确定从每个岛西的路口出发能到达多少个岛东的路口。
Solution
注意到一个条件是没有两条边相交,那么我们把东岸的点按y坐标降序排列后,任意一个西岸的点能到达的东岸一定是连续的一段。tarjan缩点之后求出一个起点能到达的最大和最小标号的终点即可本来还以为会爆栈的= =!
Code
#include <stdio.h> #include <string.h> #include <stack> #include <algorithm> #include <queue> #define rep(i,st,ed) for (int i=st;i<=ed;++i) #define fill(x,t) memset(x,t,sizeof(x)) #define read2(x,y) read(x),read(y) #define read3(x,y,z) read(x),read(y),read(z) #define max(x,y) ((x)>(y)?(x):(y)) #define min(x,y) ((x)<(y)?(x):(y)) #define INF 0x3f3f3f3f #define N 600001 #define E 4000001 struct edge{int x,y,next;}e[E]; struct pos{int x,y;}p ; std:: queue<int>que; std:: stack<int>stack; int id ,inStack ,dfn ,low ,scc ,data ,vis ; int mn ,mx ; int ls ,edCnt=0; int n,m,A,B; void read(int &x) { x=0; int v=1; char ch=getchar(); for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar()); for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar()); x*=v; } void addEdge(int x,int y) { e[++edCnt]=(edge){x,y,ls[x]}; ls[x]=edCnt; } void dfs(int now) { if (vis[now]) return ; vis[now]=1; for (int i=ls[now];i;i=e[i].next) dfs(e[i].y); } void tarjan(int now) { stack.push(now); inStack[now]=1; dfn[now]=low[now]=++dfn[0]; for (int i=ls[now];i;i=e[i].next) { if (!dfn[e[i].y]) { tarjan(e[i].y); low[now]=min(low[now],low[e[i].y]); } else if (!scc[e[i].y]) { low[now]=min(low[now],dfn[e[i].y]); } } if (dfn[now]==low[now]) { ++scc[0]; mx[scc[0]]=-INF; mn[scc[0]]=INF; for (int tmp=0;tmp!=now;) { tmp=stack.top(); stack.pop(); if (id[tmp]) { mx[scc[0]]=max(mx[scc[0]],id[tmp]); mn[scc[0]]=min(mn[scc[0]],id[tmp]); } scc[tmp]=scc[0]; inStack[tmp]=0; } } } bool cmp(int a,int b) {return p[a].y>p[b].y;} void dp(int now) { if (vis[now]) return ; vis[now]=1; for (int i=ls[now];i;i=e[i].next) { dp(e[i].y); mx[now]=max(mx[now],mx[e[i].y]); mn[now]=min(mn[now],mn[e[i].y]); } } int main(void) { read2(n,m); read2(A,B); rep(i,1,n) {read2(p[i].x,p[i].y);} rep(i,1,m) { int x,y,opt; read3(x,y,opt); addEdge(x,y); if (opt!=1) {addEdge(y,x);} } int cnt=0; rep(i,1,n) if (!p[i].x) dfs(i); rep(i,1,n) if (p[i].x==A&&vis[i]) data[++cnt]=i; std:: sort(data+1,data+cnt+1,cmp); rep(i,1,cnt) {id[data[i]]=i;} rep(i,1,n) if (!dfn[i]) {tarjan(i);} fill(ls,0); int tmp=edCnt; rep(i,1,tmp) if (scc[e[i].x]!=scc[e[i].y]) { addEdge(scc[e[i].x],scc[e[i].y]); } fill(vis,0); rep(i,1,scc[0]) dp(i); cnt=0; rep(i,1,n) if (!p[i].x) {data[++cnt]=i;} std:: sort(data+1,data+cnt+1,cmp); rep(i,1,cnt) { printf("%d\n", max(0,mx[scc[data[i]]]-mn[scc[data[i]]]+1)); } return 0; }
相关文章推荐
- jzoj 3577. 【CEOI2011】Traffic
- JZOJ3577. 【CEOI2011】Traffic
- 2387: [Ceoi2011]Traffic
- bzoj 2387: [Ceoi2011]Traffic 强连通分量+dp
- 【jzoj1938】【2011集训队出题】【Crash的数字表格】【莫比乌斯反演】
- ceoi 2011 Matching kmp
- Jzoj 2555. 【NOIP2011模拟9.7】雾雨魔理沙
- jzoj 2557. 【NOIP2011模拟9.9】单词分类
- jzoj 2544. 【NOIP2011模拟9.3】作弊的发牌者
- jzoj 2553. 【NOIP2011模拟9.7】射命丸文
- jzoj 2558. 【NOIP2011模拟9.9】过河问题
- [JZOJ1919] [BZOJ2127]【2011集训队出题】happiness(最小割之二元关系)
- jzoj1935 [2011集训队出题] 单选错位 概率水题
- JZOJ1981. 【2011集训队出题】Digit
- JZOJ-senior-2308. 【中山市选2011】聚会
- [NOI2011][JZOJ2784]阿狸的打字机
- jzoj 1951.【2011集训队出题】布娃娃 平衡树
- ceoi 2011 treasure hunt
- jzoj 2545. 【NOIP2011模拟9.3】跳舞
- {题解}[jzoj2563]【NOIP2011模拟9.15】区间运算