看了别人代码才会写的,所以只能说说自己的理解吧。
就是说建一个图,有2n个点,然后给所有(2i-1)和(2i)连一条边(1<=i<=n),然后再给所有男女朋友之间连一条边,此图无奇圈,因此是二分图。然后正常的dfs分配食物就可以让此图任意相邻两点的食物不同。但是此图不能代表真实的情况,因为真实情况下(2i)和(2i+1)以及1和2n之间也有边(1<=i<=n)。但是题目并没有要求邻座的人食物不同,而是说每连续的3个人不能全相同,所以此图的分配方法是可以满足要求的,因为(2i-1)和(2i)的食物一定不同。而任意的连续3人一定包含了某对(2i-1)和(2i)。
看完题只能想到图论呀,图论只能想到二分图呀,二分图只能想到构造呀,然后不知道该怎么构造呀。。。然后就乱搞呀。。。其实应该顺着构造的思路走下去,不该迷路的。。。有一些很显然的道路还是应该多试探一下。而不是跑到森林里挖山洞。
我一开始时这么想的,首先分法和食物编号无关,重要的是不同。其次一对男女食物不同,所以是同时分配。邻桌就用贪心,分配不同的就好了。然后就是这样的话可能会遇到死胡同(就是没法分配的情况,得回溯呀),然后构造题就变成搜索题了。自己也想过分一次男女,分一次邻桌这样,但是也会遇到死胡同,想贪心找方向,但是发现这是一个全局的过程,局部贪心是没法解决的。主要就是感觉方向跟节点编号的奇偶性有关。有些步是不能走的,一旦走了就会产生漏洞,迟早会形成奇圈的。(其实也可以以毒攻毒,错错得对= =,但只有做到一点都不错才能保证最后对啊。。。)直到最后也没想出来。。。
既然怕奇圈那就根据节点编号的奇偶性找方向啊不就完了。简直就是断了奇圈以及死胡同的所有后路呀。嗯,其实主要是断了死胡同的后路。
应该要想到从连续3点不全相同推出点对不同的。。。
代码
#include<bits/stdc++.h>
#define maxn 200010
using namespace std;
int f[maxn],x[maxn],y[maxn],t[maxn];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d %d",&x[i],&y[i]);
f[x[i]]=y[i];
f[y[i]]=x[i];
}
for(int i=1;i<=(n<<1);i++) if(!t[i])
for(int j=i,k=0;!t[j];j=k?((j-1)^1)+1:f[j],k^=1)
t[j]=2-k;
for(int i=1;i<=n;i++)
printf("%d %d\n",t[x[i]],t[y[i]]);
return 0;
}