Description
1964年的一场灾难性的洪水冲毁了萨格热布城。洪水袭来时许多建筑的墙被彻底冲毁。在这个题目中,给定了城市在洪水来袭前的简化模型,你的任务是确定洪水过后哪些墙没有被冲毁。 简化模型由平面上的N个点和W堵墙构成。每堵墙连接两个点,没有任何一堵墙通过其它点。模型具有如下性质: • 不存在两堵墙相交或者重合的情况,但是两堵墙可以在端点相连; • 每堵墙或者平行于坐标系的横轴,或者平行于坐标系的纵轴。 最开始,整个坐标平面都是干的。在零时刻,洪水将城市的外围淹没(城市的外围是指没有被墙围起来的区域)。一个小时之后,所有一边是水,一边是空气的墙在水的压力下都会倒塌。于是洪水又会吞没那些没有被完好的墙围住的区域。接下来又有一些墙面临一边是水一边是空气,将要被洪水冲毁的局面。又过了一个小时,这些墙也被冲毁了。这样的过程不断重复,直到洪水淹没整个城市。 下图给出了洪水侵袭过程的一个例子。 (图一)在零时刻,阴影的格子代表洪水区域,白色的格子代表干的区域(有空气的区域)。(图二) 一个小时之后的情况。(图三)两个小时之后,洪水淹没了整个城市,有4堵墙没有被冲毁而留了下来。 任务 给定N个点的坐标和连接这些点的W堵墙的描述,编程确定洪水过后,哪些墙会被留下来。
Input
输入的第一行包含一个整数N(2 ≤ N ≤ 100 000), 表示平面上的点的个数。 接下来的N行每行包含两个整数X和Y(都是0到1 000 000之间(包括0和1 000 000)的整数),表示点的坐标。所有点按照它们被给出的顺序编号为1到N。没有两个点在同一位置上。 接下来一行包含一个整数W(1 ≤ W ≤ 2N),表示墙的数目。 接下来W行每行包含两个不同的整数A和B(1≤ A ≤ N, 1 ≤ B ≤ N),表示在洪水到来前,有一堵墙连接A和B。这些墙按照它们被给出的顺序编号为1到W。
Output
输出的第一行包含一个整数K,表示洪水过后留下的墙的数目。 评分 有40分的测试样例,所有坐标小于等于500。 在上面的样例和另外15分的样例中,点的个数不超过500个。 中将给出一个评测结果的总结。
将原平面图转为对偶图,边权为1,计算每个结点与外围的距离,对于每条边若两侧点到外围距离相等则此边对应的墙不会被冲毁。
#include<cstdio> #include<queue> const int N=400005; int n,m; int x[N],y[N]; int e[N][4]; int id1[N][4],id2[N][4],now,ans; bool iso[N*2]; int es[N*2],enx[N*2],e0[N*2],ep=2; void addedge(int a,int b){ if(x[a]==x[b]){ if(y[a]<y[b])e[a][1]=b,e[b][3]=a; else e[a][3]=b,e[b][1]=a; }else{ if(x[a]<x[b])e[a][0]=b,e[b][2]=a; else e[a][2]=b,e[b][0]=a; } } void chk(int w){ for(int i=0;i<4;i++)if(e[w][i]){ if(!id1[w][i]){ id1[w][i]=++now; int cs=0,c; int p=e[w][i],a=i+2&3; do{ id2[p][a]=now; c=-1; while(!e[p][a+3&3])a=a+3&3,++c; cs+=c; a=a+3&3; id1[p][a]=now; p=e[p][a]; a=a+2&3; id2[p][a]=now; }while(p!=w); c=-1; while(!e[p][a+3&3])a=a+3&3,++c; cs+=c; iso[now]=cs>0; } } } int l[N*2],d[N*2]; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d%d",x+i,y+i); scanf("%d",&m); for(int i=0,a,b;i<m;i++){ scanf("%d%d",&a,&b); addedge(a,b); } for(int i=1;i<=n;i++)chk(i); for(int i=1;i<=n;i++){ for(int j=0;j<4;j++)if(e[i][j]){ int a=id1[i][j],b=id2[i][j]; es[ep]=b;enx[ep]=e0[a];e0[a]=ep++; es[ep]=a;enx[ep]=e0[b];e0[b]=ep++; } } std::queue<int>q; for(int i=1;i<=now;i++)if(iso[i])q.push(i),d[i]=1; while(!q.empty()){ int w=q.front();q.pop(); for(int i=e0[w];i;i=enx[i]){ int u=es[i]; if(!d[u]){ d[u]=1; l[u]=l[w]+1; q.push(u); } } } for(int i=1;i<=now;i++){ for(int j=e0[i];j;j=enx[j]){ if(l[i]==l[es[j]])++ans; } } printf("%d",ans/4); return 0; }