C++之路进阶——codevs2366(朋友圈)
2366 朋友圈
2012年省队选拔赛河北
在很久很久以前,曾经有两个国家和睦相处,无忧无虑的生活着。
一年一度的评比大会开始了,作为和平的两国,一个朋友圈数量最多的永远都是最值得
他人的尊敬,所以现在就是需要你求朋友圈的最大数目。
两个国家看成是 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是朋友
由于落后的古代,没有电脑这个也就成了每年最大的难题,而你能帮他们求出最大朋
友圈的人数吗?
第一行 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 国人是朋友。
输出 t 行,每行,输出一个整数,表示最大朋友圈的数目。
1
2 4 7
1 2
2 6 5 4
1 1
1 2
1 3
2 1
2 2
2 3
2 4
5
对于其中 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图所连边的点是不能算的)
代码:
1 #include<cstdio> 2 #include<iostream> 3 #define maxn 50000 4 #include<cstring> 5 #include<algorithm> 6 7 using namespace std; 8 9 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]; 10 bool map[6000][6000]; 11 12 struct ss 13 { 14 int to; 15 int next; 16 }e[maxn]; 17 18 int Cout(int x) 19 { 20 int re=0; 21 while (x) 22 { 23 x-=x&-x; 24 ++re; 25 } 26 return re; 27 } 28 29 void add(int u,int v) 30 { 31 e[++cnt].next=head[u]; 32 head[u]=cnt; 33 e[cnt].to=v; 34 } 35 36 bool find(int x) 37 { 38 if (bank[x]==T1) return 0; 39 for (int i=head[x];i;i=e[i].next) 40 if (bank[e[i].to]!=T1&&sta[e[i].to]!=T2) 41 { 42 sta[e[i].to]=T2; 43 if (tim[e[i].to]!=T1||!res[e[i].to]||find(res[e[i].to])) 44 { 45 tim[e[i].to]=T1; 46 res[e[i].to]=x; 47 return 1; 48 } 49 } 50 return 0; 51 } 52 53 int Maximum_Independent_Set(int x=0,int y=0) 54 { 55 int re=0; 56 ++T1; 57 for (int i=1;i<=B;i++) 58 if (map[x][i]||map[y][i]) 59 { 60 bank[i]=T1; 61 ++re; 62 } 63 for (int i=1;i<=B;i++) 64 if (b[i]&1) 65 { 66 ++T2; 67 if (find(i)) 68 ++re; 69 } 70 return B-re; 71 } 72 73 int main() 74 { 75 memset(map,1,sizeof map); 76 scanf("%d%d%d",&A,&B,&m); 77 for (int i=1;i<=A;i++) 78 scanf("%d",&a[i]); 79 for (int i=1;i<=B;i++) 80 scanf("%d",&b[i]); 81 for (int i=1;i<=m;i++) 82 scanf("%d%d",&x,&y),map[x][y]=0; 83 for (int i=1;i<=B;i++) 84 if (b[i]&1) 85 for (int j=1;j<=B;j++) 86 if (~b[j]&1) 87 if (~Cout(b[i]|b[j])&1) 88 add(i,j); 89 for (int i=1;i<=B;i++) 90 map[0][i]=0; 91 ans=Maximum_Independent_Set(); 92 for (int i=1;i<=A;i++) 93 ans=max(Maximum_Independent_Set(i)+1,ans); 94 for (int i=1;i<=A;i++) 95 if (a[i]&1) 96 for (int j=1;j<=A;j++) 97 if (~a[j]&1) 98 ans=max(Maximum_Independent_Set(i,j)+2,ans); 99 printf("%d",ans); 100 return 0; 101 }