csuoj 2287 Four-Coloring(图染色)

csuoj 2287 Four-Coloring

题目大意

给出一张图点与点之间连接的边的向量的角度为45°的倍数.现在有四种颜色,对图进行染色,使得所有相连接的点颜色不同

解题思路

据Misra&Gries染色算法中的颜色翻转算法,当一个点为一条双色链的端点上时,将双色链上所有的颜色翻转就可以为这个点增加一个颜色.对所有的点先x坐标再y坐标,进行排序,每次处理最后一个点,则这个点只有90°到225°之间的点是被染色了的.即其度最大为4,且由于图的性质,其四个度中只有相差90°的度可以形成环,因此其未染色的度中最多产生一个环,即其必为某种双色链的端点,对其各个度逐个翻转总能产生一种新的颜色.

AC代码

#include<bits/stdc++.h>
using namespace std;
const int size=1e4+5;
typedef pair<int,int> pii;
bool vis[5];
int col[size];
struct point
{
	pii loc;
	int id;
	point(){}
	point(int x,int y,int id):loc(pii(x,y)),id(id){}
	friend bool operator<(point a,point b)
	{
		if(a.loc==b.loc) return a.id<b.id;
		return a.loc<b.loc;
	}
};
vector<point> v;
vector<int> G[size];
int find_col(int p)
{
	memset(vis,0,sizeof(vis));
	for(auto x:G[p])
	{
		vis[col[x]]=true;
	}
	for(int i=1;i<=4;i++) if(!vis[i]) return i;
	return 0;
}
void rever(int p,int pre,int now)
{
	col[p]=pre;
	for(auto x:G[p])
	{
		if(col[x]==pre)
		{
			rever(x,now,pre);
		}
	}
}
void solve(int p)
{
	col[p]=find_col(p);
	if(col[p]) return ;
	for(auto x:G[p])
	{
		if(!col[x]) continue;
		for(int i=1;i<=4;i++){
			rever(x,i,col[x]);
			col[p]=find_col(p);
			if(col[p]) return ;
		}
	}
}
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	int x,y;
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&x,&y);
		v.push_back(point(x,y,i));
	}
	sort(v.begin(),v.end());
	int uu,vv;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&uu,&vv);
		G[uu].push_back(vv);
		G[vv].push_back(uu);
	}
	for(auto x:v) solve(x.id);
	for(int i=1;i<=n;i++) 
	{
		cout<<col[i]<<endl;
	}
}

猜你喜欢

转载自blog.csdn.net/baiyifeifei/article/details/88921826