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;
}
}