题意:
现在有一张2*n个点的图,要对其进行黑白染色,满足一下限制:
1.题中给出n对限制,要求这n对限制里每对的两个点颜色不同,保证每个点只出现一次
2.不能有连续三个点同色,注意,节点n与节点1相邻(可以看成他们坐成一个圆形)
solution:
考场懵逼= =想了个2-sat的解然而事错的。。。。。
原图中将节点2*i与2*i+1连边(记为1类边),每对限制加一条边(记为2类边),这样的图不含有奇环
原图中每个点度数一定为2,且一条1类边1条2类边
假如原图存在奇环,而环上每个点的两条边一定是一条1类一条2类交替存在
对边染色发现假设不成立
因此这样的构造是正确的,既然不存在奇环,那么这样的图是一张二分图,染色出解
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<bitset>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
const int maxn = 2E5 + 20;
int n,A[maxn],B[maxn],typ[maxn],cp[maxn];
vector <int> v[maxn];
queue <int> Q;
int pre(const int &x) {return x == 1?2*n:x - 1;}
int nex(const int &x) {return x == 2*n?1:x + 1;}
bool BFS(int x)
{
while (!Q.empty()) Q.pop();
Q.push(x); typ[x] = 0;
while (!Q.empty())
{
int k = Q.front(); Q.pop();
for (int i = 0; i < v[k].size(); i++)
{
int to = v[k][i];
if (typ[to] != -1) continue;
typ[to] = (typ[k]^1);
Q.push(to);
}
}
return 1;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
cin >> n;
for (int i = 1; i <= n; i++)
{
scanf("%d%d",&A[i],&B[i]);
cp[A[i]] = B[i];
cp[B[i]] = A[i];
v[A[i]].push_back(B[i]);
v[B[i]].push_back(A[i]);
v[2*i].push_back(nex(2*i));
v[nex(2*i)].push_back(2*i);
}
for (int i = 1; i <= 2*n; i++) typ[i] = -1;
for (int i = 1; i <= 2*n; i++)
if (typ[i] == -1) BFS(i);
for (int i = 1; i <= n; i++)
printf("%d %d\n",typ[A[i]] + 1,typ[B[i]] + 1);
return 0;
}