清北test2+cf547D 點轉成邊建圖
阿新 • • 發佈:2018-12-18
傳送門
重點!!!!!!!!!!!!
- dfs過程中,遍歷時必須要加取地址符號,這樣可以實時的刪去 邊表裡的邊,防止多次訪問超時(有vis陣列也不行,因為還會進到迴圈裡判斷)!!!!
思路
- 點(x,y)可以轉化為點x和點y連一條邊,這樣now邊(x,y)表示past點,now點表示past一橫行或一豎列
- 這要保證連入now點的邊中黑-白<=1即可
#include<bits/stdc++.h> #define ll long long using namespace std; struct edge{ int to,next,ind; }ed[10000010]; int color[10000010],head[10000010], sz,x[5000010],y[5000010],sum[2000000], vis[10000010],nn,n,b[10000010],cnt, du[10000010],cnt1; const int ss=0; void add_edge(int from,int to,int ind) { ed[++cnt1].to=to; ed[cnt1].next=head[from]; ed[cnt1].ind=ind; head[from]=cnt1; } int read() { int x=0,flag=1;char c=getchar(); while(!isdigit(c)) {if(c=='-') flag=-1;c=getchar(); } while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x*flag; } void dfs(int u) { for(int &i=head[u];i;i=ed[i].next) { int v=ed[i].to,ind=ed[i].ind; if(vis[ind]) continue; if(v>nn) color[ind]=1; else color[ind]=0; vis[ind]=1; dfs(v); } } int main() { //freopen("color.in","r",stdin); //freopen("color.out","w",stdout); scanf("%d",&n); nn=2*n; for(int i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]),b[++cnt]=x[i],b[++cnt]=y[i]; sort(b+1,b+cnt+1); int sz=unique(b+1,b+cnt+1)-b-1; for(int i=1;i<=n;i++) { x[i]=lower_bound(b+1,b+sz+1,x[i])-b; y[i]=lower_bound(b+1,b+sz+1,y[i])-b; } for(int i=1;i<=n;i++) { add_edge(x[i],y[i]+nn,i); add_edge(y[i]+nn,x[i],i); du[x[i]]++; du[y[i]+nn]++; } int tot=n; for(int i=1;i<=n;i++) { if(du[x[i]]&1) tot++,add_edge(x[i],ss,tot),add_edge(ss,x[i],tot),du[x[i]]++; if(du[y[i]+nn]&1) tot++,add_edge(y[i]+nn,ss,tot),add_edge(ss,y[i]+nn,tot),du[y[i]+nn]++; } for(int i=1;i<=2000000;i++) dfs(i); for(int i=1;i<=n;i++) cout<<color[i]<<' '; return 0; }