您的位置:首页 > 编程语言 > C语言/C++

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: