BZOJ1804: [Ioi2007]Flood 洪水

把点按坐标排序,每次找出最小的点,一定在最外层,再顺着把最外层的边删掉,经过了两次的边不会被冲毁。

#include<bits/stdc++.h>
using namespace std;
const int N=4e5+5;
int n,m,y,q[N],x[N],e[N],*back=e,*f[N][4];
struct vec{
	int x,y,z;
}a[N],r[N];
bool operator<(vec u,vec v){
	return u.x<v.x||u.x==v.x&&u.y<v.y;
}
int foo(int i,int j){
	return a[i].x==a[j].x?a[i].y<a[j].y?3:1:a[i].x<a[j].x?2:0;
}
void add(int u,int v){
	f[u][foo(u,v)]=&(*back++=v);
	f[v][foo(v,u)]=&(*back++=u);
}
bool test(int i){
	for(int j=0;j!=4;++j)
		if(f[i][j])return 1;
	return 0;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i){
		a[i].z=i;
		scanf("%d%d",&a[i].x,&a[i].y);
		r[i]=a[i];
	}
	scanf("%d",&m);
	for(int i=1;i<=m;++i){
		int u,v;
		scanf("%d%d",&u,&v);
		add(u,v);
	}
	sort(r+1,r+n+1);
	for(int i=1;i<=n;++i)
		while(test(r[i].z)){
			int l=0,j=2,k=r[i].z;
			do{
				j=j+3&3;
				while(!f[k][j])
					++j&=3;
				++x[(q[l++]=f[k][j]-e)>>1];
				k=*f[k][j];
			}while(k!=r[i].z);
			for(int j=0;j!=l;++j){
				int u=e[q[j]],v=e[q[j]^1];
				f[u][foo(u,v)]=0;
				f[v][foo(v,u)]=0;
			}
		}
	for(int i=0;i!=m;++i)
		y+=x[i]==2;
	printf("%d\n",y);
}
posted @ 2016-06-13 16:40  f321dd  阅读(396)  评论(0编辑  收藏  举报