1. 程式人生 > >清北test2+cf547D 點轉成邊建圖

清北test2+cf547D 點轉成邊建圖

傳送門

重點!!!!!!!!!!!!

  1. dfs過程中,遍歷時必須要加取地址符號,這樣可以實時的刪去 邊表裡的邊,防止多次訪問超時(有vis陣列也不行,因為還會進到迴圈裡判斷)!!!!

思路

  1. 點(x,y)可以轉化為點x和點y連一條邊,這樣now邊(x,y)表示past點,now點表示past一橫行或一豎列
  2. 這要保證連入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;
}