您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: