~~ 果然图的问题都是难在建图~~
题意:
有n对情侣(2n个人)围成一圈坐在桌子边上, 每个人占一个座位,要求情侣不能吃一样的食物,并且桌子上相邻的三个人的食物必须有两个是不同的,只有两种食物(1,2),给出一种可行的分配方式。1 <= n <= 1e5。
思路:
由题意可知,食物只有两种且情侣不能吃一样的食物,相邻的三个人的食物必须有两个是不同的, 就可以想到二分图。
- 如果给不能吃同样食物的两个人连一条边,问题就变成了二分图黑白染色
- 所以情侣之间需要连一条边。
- 剩下来就是解决相邻三个人的问题了:
- 让第2i 与 第2i + 1的人吃不一样的食物即可(即1连2, 3连4, 5连6 …)
- 这样可定是个二分图 – 2i 和2i - 1 分别连了他们情侣,情侣分别连他们的邻居,邻居再连他们的情侣…每次都是给这可能存在的环加两个点,所以环一定不是奇环。
建完图后二分图染色就好了
代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef pair<int, int> PII;
const int maxn = 3e5 + 7;
int h[maxn], e[maxn<<1], ne[maxn<<1], cnt;
int color[maxn<<1];
void add(int u, int v){
e[cnt] = v;
ne[cnt] = h[u];
h[u] = cnt ++;
e[cnt] = u;
ne[cnt] = h[v];
h[v] = cnt ++;
}
void dfs(int u, int c){
color[u] = c;
for (int i = h[u]; ~i; i = ne[i]){
int v = e[i];
if (color[v]) continue;
dfs(v, 3 - c);
}
}
vector<PII> p;
int main(){
int n;
scanf ("%d", &n);
for (int i = 0; i <= 2*n; i ++ ) h[i] = -1;
for (int i = 1; i <= 2*n; i += 2 ) add(i, i + 1);
for (int i = 1, u, v; i <= n; i ++ ){
scanf ("%d%d", &u, &v);
add(u, v);
p.push_back({u,v});
}
for (int i = 1; i <= 2 * n; i ++ ){
if (!color[i]) dfs(i, 1);
}
for (int i = 0; i < n; i ++ ){
printf ("%d %d\n", color[p[i].first], color[p[i].second]);
}
return 0;
}