jzoj 3577. 【CEOI2011】Traffic
来源:互联网 发布:双机热备 数据库 编辑:程序博客网 时间:2024/05/16 23:44
Description
Gdynia 的中心坐落于Kacza 河中游的一个岛屿上。每天早晨,成千辆小车从河流的西岸的住宅区出发穿过岛屿(使用连接岛西路口的桥梁)到达东岸的工业区(使用连接岛东路口的桥梁)。
这个岛屿酷似一个边平行于坐标轴的矩形。因此,我们视他为一个笛卡尔坐标系上的A*B的矩形,对角的坐标为(0,0) 和(A,B)。
在这个岛屿上,有n 个路口从1 到n 编号。路口i 位于坐标(xi; yi)。如果一个路口坐标类似于(0,y),那么它在岛西。类似的,坐标形于(A,y) 的路口坐落在岛东。路口通过街道连接起来。每一条街道是一条连接两个路口的线段。街道可以是双向或者单向的。没有两条街道有公共点(除了作为线段端点的路口)。岛上没有桥或者地道。其他的道路网络形状是不被认可的。特别的是,街道可以与岛屿的边缘重合,或者存在没有连接街道的路口。
因为交通密度不断增长,所以市长雇佣你去检查现在的道路网络是否足够。他要求你写一个程序,确定从每个岛西的路口出发能到达多少个岛东的路口。
Input
输入的第一行包含四个整数n,m,A和B(1<=n<=300 000; 0<=m<=900 000; 1<=A,B<=10^9)。他们分别表示Gdynia 中心的路口数、街道数和岛屿的尺寸。
在接下来n 行的每一行中有两个整数xi,yi(0<=xi<=A, 0<= yi<= B),描述路口i 的坐标。没有两个路口有相同的坐标。
接下来的m 行描述街道。每条街道用单独的一行表示,每行包含三个整数ci, di, ki(1<= ci, di<=n; ci ̸= di; ki=1或2)。它们的意思是,路口ci 和di 被一条街道连接。如果ki = 1,那么这是一条从ci 到di 的单向道路。否则,这条道路是双向的。每个无序对{ci,di}在输入中最多出现一次。
你可以认为,有至少一个在岛西的路口可能到达岛东的一些路口。
Output
你的程序应该对于每个岛西的路口都输出一行。这一行应该是这个路口能到达的岛东的路口个数。输出的顺序按照岛西路口y 坐标从大到小输出。
Sample Input
输入1:
5 3 1 3
0 0
0 1
0 2
1 0
1 1
1 4 1
1 5 2
3 5 2
输入2:
12 13 7 9
0 1
0 3
2 2
5 2
7 1
7 4
7 6
7 7
3 5
0 5
0 9
3 9
1 3 2
3 2 1
3 4 1
4 5 1
5 6 1
9 3 1
9 4 1
9 7 1
9 12 2
10 9 1
11 12 1
12 8 1
12 10 1
Sample Output
输出1:
2
0
2
输出2:
4
4
0
2
Data Constraint
在总值30points 的数据里,n,m<=6 000。
traffic解题报告(by jzoj)
【题目大意】
给出一个平面图,每个点的X坐标都在区间[0,A]内,每个点的Y坐标都在区间[0,B]内,没有重点。一些点之间有边,边分为双向边和单向边。要求问每个X=0的点能到达的不同的X=A的节点个数。
平面图有n个点,m条边,给出A,B,每个点的坐标,每条边连接的两个点和每条边的类型。n<=300000,m<=900000,A,B<=10^9。按照Y坐标递减的顺序输出每个X=0的点能到达的不同的X=A的节点个数。时限8s。
【题目关键字】
平面图,floodfill,BFS
【算法讨论】
如图,首先从每个所有X=0的点出发做一遍floodfill,然后把没有任何X=0的点能到达的X=A的节点删除。把所有X=A的节点按照Y坐标从小到达排序,因为该图是平面图,所以每个点能到达的X=A的节点一定是连续的一段。那么按照Y递增的顺序从每个X=A的节点出发在反图上做一遍floodfill,然后按照Y递减的顺序从每个X=A的节点出发在反图上做一遍floodfill,记录下两次过程中每个被染色的时间,即可算出每个点可达的X=A的节点数。
因为这题n较大,所以floodfill最好用BFS实现。BFS总的时间复杂度为O(n+m),排序操作总的时间复杂度为O(nlogn),最后总的时间复杂度为O(m+nlogn),对于8s的时限可以轻松通过本题。
【时空复杂度】
时间复杂度:O(m+nlogn)
空间复杂度:O(n)
代码:
# include <cstdlib> # include <cstdio> # include <cmath> # include <cstring> using namespace std; const int maxn=300000+10, maxm=900000+10, oo=1073741819; int top,top2,link2[maxm*3], next2[maxm*3], sum2[maxm*3],linke[maxm*3], next[maxm*3], sum[maxm*3]; int low[maxn], dfn[maxn], w[maxn],st[maxn]; bool step[maxn], stay[maxn]; int id[maxn], place[maxn], pt[maxn], pe[maxn], pb[maxn],l[maxn], r[maxn]; int n,m,A,B,tot,time; void link(int x, int y) {++top; next[top]=linke[x]; linke[x]=top; sum[top]=y;}; inline int min(int x, int y) {return x<y?x:y;}; inline int max(int x, int y) {return x>y?x:y;}; void tarjan(int p) { int ke=linke[p],now;low[p]=dfn[p]=++time;st[++tot]=p; step[p]=true; stay[p]=true; for (;ke!= 0; ke=next[ke]) if (!step[sum[ke]]) tarjan(sum[ke]), low[p]=min(low[p], low[sum[ke]]); else if (stay[sum[ke]]) low[p]=min(low[p], dfn[sum[ke]]); if (dfn[p]==low[p]) { for (now=st[tot];now!=p;now=st[--tot]) id[now]=p, w[p]+= w[now], stay[now]=false, l[p]=min(l[p],l[now]), r[p]=max(r[p],r[now]); tot--; stay[now]=false; } } void dfs(int p) { int ke=link2[p]; step[p]=true; for (;ke!=0; ke=next2[ke]) { if (!step[sum2[ke]]) dfs(sum2[ke]), step[sum2[ke]]=true; r[p]=max(r[p], r[sum2[ke]]); l[p]=min(l[p],l[sum2[ke]]); } } void sort(int pt[maxn], int l, int r) { int i=l, j=r, tmp,d=place[pt[l+r>>1]]; for (;i <= j;) { for (;place[pt[i]] < d;i++); for (;place[pt[j]] > d;j--); if (i <= j) tmp=pt[i],pt[i]=pt[j],pt[j]=tmp,i++,j--; } if (i<r) sort(pt,i,r); if (l<j) sort(pt,l,j); } void linke2(int x, int y) { ++top2; next2[top2]=link2[x];link2[x]=top2;sum2[top2]=y; }; void dfs2(int p) { step[p]= true; for (int ke=link2[p]; ke!= 0; ke=next2[ke]) if (!step[sum2[ke]])dfs2(sum2[ke]); } void prepare() { int i,x,y,z; sort(pt,1,pt[0]); sort(pb,1,pb[0]); for (i = 1; i <= m; i++) { scanf("%d%d%d",&x, &y, &z); linke2(x,y); if (z==2) linke2(y,x); } for (i = 1; i <= pt[0]; i++) dfs2(pt[i]); for (i = 1; i <= n; i++) for (int ke=link2[i]; ke!= 0; ke=next2[ke]) if (step[i] && step[sum2[ke]]) link(i, sum2[ke]); for (i = 1; i <=pb[0]; i++) if (step[pb[i]]) pe[++pe[0]] = pb[i], l[pb[i]]=r[pb[i]]=pe[0]; memset(next2, 0, sizeof(next2)); memset(sum2, 0, sizeof(sum2)); memset(link2, 0, sizeof(link2)); memset(step, 0, sizeof(step)); top2=0; } int main() { int i,x,y; //freopen("traffic.in", "r", stdin); //freopen("traffic.out", "w", stdout); scanf("%d%d%d%d", &n, &m, &A, &B); for (i = 1; i <= n; i++) { scanf("%d%d", &x, &y); place[i]=y; l[i]=oo; r[i]=-oo; if (x==0) pt[++pt[0]]=i; else if (x==A) pb[++pb[0]]=i; } prepare(); memset(step, false, sizeof(step)); for (i =1; i <= n; i++) id[i]=i; for (i = 1; i <= n; i++) if (!step[i]) tarjan(i); memset(step, false, sizeof(step)); for (i = 1; i <= n; i++) for (int ke=linke[i]; ke!= 0; ke=next[ke]) if (id[i]!= id[sum[ke]]) linke2(id[i], id[sum[ke]]); for (i = 1; i <= n; i++) if (!step[i]) dfs(i); for (i = pt[0]; i >= 1; i--) if (r[id[pt[i]]] != -oo) printf("%d\n", r[id[pt[i]]]-l[id[pt[i]]]+1); else printf("0\n"); return 0; }
- jzoj 3577. 【CEOI2011】Traffic
- [jzoj]3577. 【CEOI2011】Traffic(转化模型+Floodfill)
- JZOJ3577. 【CEOI2011】Traffic
- 2387: [Ceoi2011]Traffic
- bzoj 2387: [Ceoi2011]Traffic 强连通分量+dp
- jzoj3577 [CEOI2011]Traffic 强连通分量缩点
- CEOI2011 mat solution中文翻译
- ceoi2011选做
- ceoi2011 切题记
- BZOJ 2386: [Ceoi2011]Team
- [CEOI2011] balloons 单调栈
- Traffic topic
- Vechile & Traffic
- Heavy Traffic
- Traffic Controll
- Continue to verify traffic!
- ARP traffic generation tools
- SGU 103 Traffic Lights
- 一个很好的银行对账工具软件
- E企播报:阿里云纵深,万达云尴尬
- python的pip日常使用
- 堆排序
- maven的安装及与Myeclipse的整合
- jzoj 3577. 【CEOI2011】Traffic
- 基础算法
- 学习笔记-jQuery扩展示例
- Django 之 ORM 基础
- 编程中的经典语句
- 运营思略:APP线上运营方案 | PUSH营销篇
- HEVC标准中的图像分割(1),slice,tile,CTU,CU,PU,TU等
- 校门外的树
- scau 11075 强盗分赃