C++之路进阶——最大流(朋友圈)
2016-02-15 20:54
483 查看
2366 朋友圈
2012年省队选拔赛河北时间限制: 10 s
空间限制: 256000 KB
题目等级 : 大师 Master
题目描述 Description
在很久很久以前,曾经有两个国家和睦相处,无忧无虑的生活着。
一年一度的评比大会开始了,作为和平的两国,一个朋友圈数量最多的永远都是最值得
他人的尊敬,所以现在就是需要你求朋友圈的最大数目。
两个国家看成是 AB 两国,现在是两个国家的描述:
1、 A 国:每个人都有一个友善值,当两个 A 国人的友善值 a、b,如果 a xor b mod 2=1,
那么这两个人都是朋友,否则不是;
2、 B 国:每个人都有一个友善值,当两个 B 国人的友善值 a、b,如果 a xor b mod 2=0
或者 (a or b)化成二进制有奇数个 1,那么两个人是朋友,否则不是朋友;
3、 A、B 两国之间的人也有可能是朋友,数据中将会给出 A、B之间“朋友”的情况。
4、 对于朋友的定义,关系是是双向的。
在 AB 两国,朋友圈的定义:一个朋友圈集合 S,满足
S属于A并B,对于所有的 i,j属于S,i 和 j是朋友
由于落后的古代,没有电脑这个也就成了每年最大的难题,而你能帮他们求出最大朋
友圈的人数吗?
输入描述 Input Description
第一行 t<=6,表示输入数据总数。
接下来 t 个数据:
第一行输入三个整数 A,B,M,表示A国人数、B 国人数、AB 两国之间是朋友的对数;
第二行 A 个数 ai,表示A 国第i 个人的友善值;
第三行 B 个数 bi,表示B 国第j 个人的友善值;
第 4——3+M行,每行两个整数(i,j) ,表示第i 个A 国人和第 j 个B 国人是朋友。
输出描述 Output Description
输出 t 行,每行,输出一个整数,表示最大朋友圈的数目。
样例输入 Sample Input
1
2 4 7
1 2
2 6 5 4
1 1
1 2
1 3
2 1
2 2
2 3
2 4
样例输出 Sample Output
5
数据范围及提示 Data Size & Hint
对于其中 30%的数据,A=0,B<=100;
对于其中 50%的数据,A<=10,B<=100;
对于其中 10%的数据,A<=5,B<=1000;
对于其中 10%的数据,A<=5,B<=1500;
对于 100%的数据,M<=A*B,友善值在2^30 以内。
题解:
对与A图而言,奇数与奇数相连,偶数与偶数相连,A图中只能选一个或者不选,最多一奇一偶,对于B图而言,求最大团,建立反边,求最大独立子集,(ps:原本与A图所连边的点是不能算的)
代码:
#include<cstdio> #include<iostream> #define maxn 50000 #include<cstring> #include<algorithm> using namespace std; int m,head[maxn],A,B,a[maxn],b[maxn],x,y,cnt=0,ans,T1,T2,bank[maxn],res[maxn],tim[maxn],sta[maxn]; bool map[6000][6000]; struct ss { int to; int next; }e[maxn]; int Cout(int x) { int re=0; while (x) { x-=x&-x; ++re; } return re; } void add(int u,int v) { e[++cnt].next=head[u]; head[u]=cnt; e[cnt].to=v; } bool find(int x) { if (bank[x]==T1) return 0; for (int i=head[x];i;i=e[i].next) if (bank[e[i].to]!=T1&&sta[e[i].to]!=T2) { sta[e[i].to]=T2; if (tim[e[i].to]!=T1||!res[e[i].to]||find(res[e[i].to])) { tim[e[i].to]=T1; res[e[i].to]=x; return 1; } } return 0; } int Maximum_Independent_Set(int x=0,int y=0) { int re=0; ++T1; for (int i=1;i<=B;i++) if (map[x][i]||map[y][i]) { bank[i]=T1; ++re; } for (int i=1;i<=B;i++) if (b[i]&1) { ++T2; if (find(i)) ++re; } return B-re; } int main() { memset(map,1,sizeof map); scanf("%d%d%d",&A,&B,&m); for (int i=1;i<=A;i++) scanf("%d",&a[i]); for (int i=1;i<=B;i++) scanf("%d",&b[i]); for (int i=1;i<=m;i++) scanf("%d%d",&x,&y),map[x][y]=0; for (int i=1;i<=B;i++) if (b[i]&1) for (int j=1;j<=B;j++) if (~b[j]&1) if (~Cout(b[i]|b[j])&1) add(i,j); for (int i=1;i<=B;i++) map[0][i]=0; ans=Maximum_Independent_Set(); for (int i=1;i<=A;i++) ans=max(Maximum_Independent_Set(i)+1,ans); for (int i=1;i<=A;i++) if (a[i]&1) for (int j=1;j<=A;j++) if (~a[j]&1) ans=max(Maximum_Independent_Set(i,j)+2,ans); printf("%d",ans); return 0; }
相关文章推荐
- c语言:输入两个正整数m和n,求其最大公约数和最小公倍数
- 值得推荐的C/C++框架和库 (真的很强大)
- x265-1.8版本-encoder/slicetype.cpp注释
- x265-1.8版本-encoder/ratecontrol.cpp注释
- 重学C++ (十一) OOP面向对象编程(2)
- C++继承与派生
- x265-1.8版本-encoder/motion.cpp注释
- C++11新特性之move与forward
- x265-1.8版本-encoder/level.cpp注释
- 树状树组(Binary Indexed Tree (BIT))的C++部分实现
- x265-1.8版本-encoder/frameencoder.cpp注释
- x265-1.8版本-encoder/dpb.cpp注释
- x265-1.8版本-encoder/bitcost.cpp注释
- leetcode326题 题解 翻译 C语言版 Python版
- x265-1.8版本-common/wavefront.cpp注释
- USACO US OPEN 2015 BRONZE 三四题 C++翻译代码
- c语言:用8个2*1的小矩形横着或竖着无重叠地覆盖一个2*8的大矩形,总共有多少种方法?
- glibc detected
- c语言:一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法?
- C++学习之primer