Codeforces Round# 305 (Div 1)

Posted _Horizon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round# 305 (Div 1)相关的知识,希望对你有一定的参考价值。

[Codeforces 547D]

题目大意:平面上有n个点,你需要给他们一一染色,可以染‘b‘(blue)或‘r‘(red),要求每一行和每一列所染色的(红色-蓝色)数目的绝对值<=1,输出染色方案。

n ≤ 2 * 10^5

 

 

QAQ虽然说一看就知道是网络流但是数据范围也是吓我一跳QAQ

然而YY半天建图无果。。

首先行和列示要看成点的,给的每一个点(x, y)看成一条边无疑,容量为1

然后广告犇提出了限流思想:既然每行或每列不能相差超过1,那么就可以从源点->每一行连接容量为(cntx[i] / 2)的边,这样红蓝就一定符合条件了!(其中cntx[i]表示第i行有多少个点),从每一列连向汇点同理QAQ

但是这样输出的方案可能还不够,有一些点仍然没有确定怎么办?(假如某一行某一列的点的个数为奇数。。)

然后就弃疗了

orz了一下神犇的题解(虽然说并不知道神犇是谁,但是网络流竟然可以过QAQ)

先把行列离散化一下QAQ,然后如上建边,然后跑一边最大流,然后如果有多出来的就再添加一条容量为1的边,再跑一遍最大流。最后如果割掉了(edge[i<<1])说明此点和S相连,否则和T相连。

某犇:我快YY出正解了

主要程序:(网络流就不写了QAQ)

int main(){
	scanf("%d", &n);
	for(int i = 1; i <= n; i ++)
	    scanf("%d%d", &x[i], &y[i]);
    for(int i = 1; i <= n; i ++)
        ++ cx[x[i]], ++ cy[y[i]];
	int id = 0;
	for(int i = 1; i <= 200000; i ++)
		if(cx[i])Idx[i] = ++ id;
    for(int i = 1; i <= 200000; i ++)
		if(cy[i])Idy[i] = ++ id;
	T = id + 1;
	for(int i = 1; i <= n; i ++)
	    add(Idx[x[i]], Idy[y[i]], 1);
	for(int i = 1; i <= 200000; i ++)
		if(cx[i] > 1) add(S, Idx[i], cx[i] >> 1);
    for(int i = 1; i <= 200000; i ++)
		if(cy[i] > 1) add(Idy[i], T, cy[i] >> 1);
	
	Dinic();
	for(int i = 1; i <= 200000; i ++)
	    if(cx[i] & 1) add(S, Idx[i], 1);
    for(int i = 1; i <= 200000; i ++)
	    if(cy[i] & 1) add(Idy[i], T, 1);
	Dinic();
	for(int i = 1; i <= n; i ++)
	    if(!edge[i<<1].w)
			putchar(‘b‘);
		else putchar(‘r‘);
	puts("");
	return 0;
}

  

以上是关于Codeforces Round# 305 (Div 1)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces round FF

Codeforces Round #436 E. Fire(背包dp+输出路径)

[ACM]Codeforces Round #534 (Div. 2)

codeforces #305 div1 done

Codeforces Round #726 (Div. 2) B. Bad Boy(贪心)

Continued Fractions CodeForces - 305B (java+高精 / 数学)