1. 程式人生 > >【bzoj4423】[AMPPZ2013]Bytehattan(平面圖轉對偶圖+並查集)

【bzoj4423】[AMPPZ2013]Bytehattan(平面圖轉對偶圖+並查集)

  題目傳送門:bzoj4423

  如果是普通的刪邊判連通性,我們可以很顯然的想到把操作離線下來,倒著加邊。然而,這題強 制 在 線

  雖然如此,但是題目所給的圖是個平面圖。那麼我們把它轉成對偶圖試試看?

  在對偶圖上,刪邊變成了加邊(把邊兩邊的網格連通起來)。並且,我們可以發現,如果在對偶圖上加邊時發現出現了一個環,那麼就說明這個環中間的格點被完全同外面的格點切斷了聯絡(包括剛才刪去的邊兩側的點)。

  於是我們就只需在對偶圖上用並查集維護對偶圖的連通性即可。

  程式碼:

#include<cstdio>
#define maxn 1510
using
namespace std; int fa[maxn*maxn]; int n,m,lastans; inline int getid(int x,int y) { if(x<1||y<1||x>=n||y>=n)return 0; else return (x-1)*n+y; } int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);} void work(int x,int y,char op) { int f1,f2; if(op=='N')f1=find(getid(x-1
,y)),f2=find(getid(x,y)); else f1=find(getid(x,y-1)),f2=find(getid(x,y)); if(f1==f2)printf("NIE\n"),lastans=0; else fa[f1]=f2,printf("TAK\n"),lastans=1; } int main() { scanf("%d%d",&n,&m); lastans=1; for(int i=0;i<=n*n;i++)fa[i]=i; for(int i=1;i<=m;i++){
int x1,y1,x2,y2; char c1,c2; scanf("%d %d %c %d %d %c",&x1,&y1,&c1,&x2,&y2,&c2); if(lastans)work(x1,y1,c1); else work(x2,y2,c2); } }
bzoj4423