Codeforces Round# 305 (Div 1)
Posted _Horizon
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round# 305 (Div 1)相关的知识,希望对你有一定的参考价值。
题目大意:平面上有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 #436 E. Fire(背包dp+输出路径)
[ACM]Codeforces Round #534 (Div. 2)