标签:
将原平面图转为对偶图,边权为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; }
标签:
原文地址:http://www.cnblogs.com/ccz181078/p/5427442.html