[Codeforces741C]Arpa’s overnight party and Mehrdad’s silent entering(二分图染色)

http://codeforces.com/contest/741/problem/C


题目描述
  要不我就用这次模拟考的题面吧哈哈哈写的好有趣:
  七夕节,有 对情侣围做在一个圆桌上吃饭。座位的编号为 1~2n(1<=n<=10^5) 。饭店老板作为大FFF团的一员,看着这一桌,身旁不知何时多了一根火把。 他想了想,觉得火把太暴力了,要让敌人从内部瓦解。于是,他决定让一对情侣两个人一个吃好吃的食物,一个吃难吃的食物,这样他们就会产生分歧,感情出现裂痕…… 同时,任意连续3人也不能都吃到难吃的食物或都吃到好吃的食物。注意:1 和 2n是相邻的。老板现在还沉浸在想出这个妙招的喜悦中,分配食物的方案就交给你了。

输入格式
第一行一个数 ,表示情侣的对数。
接下来 行,每行两个数,分别表示第 对情侣两个人就座的位置。
输入保证每个位置恰好有一个人坐。
输出格式
如果有解,则输出 行,每行两个数,表示第 对情侣两个人的食物。 代表难吃的, 代表好吃的。 无解输出 -1

样例输入
3
1 4
2 5
3 6
样例输出
1 2
2 1
1 2


解法:
  这道题有两个突破点:
  1、情侣要不同
  2、相邻的三个人不能相同
  那么我们考虑把每个人看成一个点,构一个图,用黑白染色的方法来让一条边的两端的点不一样。那么怎么构图呢?
  显而易见,要满足条件1,对情侣之间连一条无向边即可。
  要满足条件2,我们可以对2i和2i-1连一条无向边(也就是1–2,3–4),为什么,举个例子,假如我们现在是1–2,3–4,最坏的情况是2,3相同,但是由于1和2相连,3和4相连所以1和2不同,3和4不同,所以不会有连续三个相同的情况。


#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
    int x,y,next;
}t[400010]; int len,last[200010];
void ins(int x,int y)
{
    t[++len].x=x;t[len].y=y;
    t[len].next=last[x];last[x]=len;    
}
int a[200010],b[200010],ans[200010];
void dfs(int x,int w)
{
    ans[x]=w;
    for(int k=last[x];k;k=t[k].next)
    {
        int y=t[k].y;
        if(!ans[y]) dfs(y,3-w);
    }
}
int main()
{
    int n; scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&a[i],&b[i]);
        ins(a[i],b[i]);
        ins(b[i],a[i]);
    }
    for(int i=1;i<=n;i++)
    {
        ins(i*2-1,i*2);
        ins(i*2,i*2-1); 
    }
    for(int i=1;i<=2*n;i++)
        if(!ans[i])
            dfs(i,1);
    for(int i=1;i<=n;i++)
        printf("%d %d\n",ans[a[i]],ans[b[i]]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值