首页 > 代码库 > [codevs5578][咸鱼]tarjan/结论题
[codevs5578][咸鱼]tarjan/结论题
5578 咸鱼
在广袤的正方形土地上有n条水平的河流和m条垂直的河流,发达的咸鱼家族在m*n个河流交叉点都建立了城市。然而,由于河流有单一的流向,而咸鱼们却没有发达的下体,所以只能顺流而下。两两河流之间的流向互不影响。
现在,咸鱼冒险家Sorey决定出发去看看这个世界,但是Sorey担心自己可能被困在某个城市而无法回归自己的家乡。于是Sorey夜观天象,搞清楚了每条河的流向,他想请你帮他判断他的旅途是否会顺利。
第一行一个整数T,表示数据组数(T<=10)
每组数据第一行两个整数n,m,含义如上述
第二行两个整数x,y,表示Sorey的初始坐标(从一开始,x表示所在行,y表示所在列)
下一行n个数,之间用空格间隔,其中第i个表示第i条水平河流的方向,0向左,1向右
下一行m个数,之间用空格间隔,其中第i个表示第i条垂直河流的方向,0向下,1向上
一组数据一行
如果Sorey能到达任何一座城市且不可能被困住的话,输出"Yes.",否则输出"No."(不含引号)
1
4 6
1 1
0 1 0 1
0 1 0 1 0 1
Yes.
样例如图
对于40%的数据n,m<100,T=1;
对于60%的数据n,m<1000;
对于100%的数据2<=n,m<=1000000,1<=x<=n,1<=y<=m;
数据很大,注意读入优化
分析:
“咸鱼们却没有发达的下体”以及Yes后面的句号,槽点还是挺多的。数据范围很大,应该是结论题
推论1:
看这句话“但是Sorey担心自己可能被困在某个城市而无法回归自己的家乡”以及“如果Sorey能到达任何一座城市且不可能被困住的话,输出"Yes.",否则输出"No."(不含引号)”,显然题目要求我们判断是否可以从源点s到任何一个点且可以从任何一个点回到源点s,即任意两点i,j互相可达(i到s,再s到j),所以,要求原图是强连通分量。用tarjan算法即可判断。但是复杂度O(nm),只有60分。
推论2:
我们必须优化到O(n)或以下,考虑特判,看了一下样例发现:只需要最外围是一个环就一定满足,因为从s沿边走就一定可以到外围,在外围绕圈到每一条边的入口即可进去。
推论3:
充分性以证,只需完备性即可:只要最外围不是环,那么四个顶角必然有的只能进不能出,不可能是强连通分量。
现在只需要判断最外围是不是环即可,复杂度O(1),但数据太大,要优化读入,可以用fseek跳过中间部分,用getchar()也能过(偷懒的我用的后者,复杂度O(n+m))
1 #include<cstdio> 2 inline int read(){ 3 char c=getchar(); 4 while(c!=‘0‘&&c!=‘1‘) c=getchar(); 5 return c-‘0‘; 6 } 7 int main(){ 8 int n,m,x,y,a,b,c,d,T; 9 scanf("%d",&T); 10 while(T--){ 11 scanf("%d %d %d %d",&n,&m,&x,&y); 12 a=read();n-=2; 13 while(n--) read(); 14 b=read();c=read();m-=2; 15 while(m--) read(); 16 d=read(); 17 if((a==0&&b==1&&c==0&&d==1)|| 18 (a==1&&b==0&&c==1&&d==0)) printf("Yes.\n"); 19 else printf("No.\n"); 20 } 21 return 0; 22 }
[codevs5578][咸鱼]tarjan/结论题