HEOI2012 朋友圈
2012-05-10 11:21
204 查看
这是做的最得意的一道题,当时在考场上得了90,是因为数据中A有100++的情况,Runtime_error了。。
首先强调,本人不是用二分图,或者说不用图论算法,只涉及简单的枚举和记忆化思想。
A国的人最多只能取两个,这个大家都能看出来,当然还可能不取。
B国的人不去向常规考虑奇偶分组,这个会在后面提到。
题意抽象为求一个最大完全图,那么当我们确定一个极大完全图后,任意一个元素都可以作为代表元,给定代表元之后,通过一边O(n)的扫描就能得到这个极大完全图。
所以对于不含A国人的情况,我们只需要枚举一个B国人,把其他的B国人尽量多的加进去,这个加人的顺序与结果无关,而代表元可以使任意一个,因此可以用一个数组记录v[x]表示是否求过以x为代表元的集合。
对于有A国人的情况,枚举一个A国人,再枚举一个B国人,同理他们构成的最大完全图也就确定了,同样可以使用记忆化来降低枚举时间。
对于两个A国人的情况,一样处理即可。
程序有两个记录数组v1,v2,由于A,B的人数差距极大,用一个数组记录就需要开10*10*1500,但是事实上的数据会达到200*200*3000,极大的超内存,所以采用分开处理的方式,A较小B较大时用200*200*200的数组,A极小B很大时用50*50*3000的,内存就很充裕了。
而对于时间复杂度,为最大枚举数O(sa*sa*sb*sb),加入的v数组会让它达不到这个极限。
事实证明,时限为20S的题目,我的程序通过最大点的时间仅为2s++
如有反例,欢迎提出。
View Code
注:BZOJ上仅有一组数据且输入没有T,直接按一组数据做即可。
本随笔为原创,如要转载,请注明出处。
首先强调,本人不是用二分图,或者说不用图论算法,只涉及简单的枚举和记忆化思想。
A国的人最多只能取两个,这个大家都能看出来,当然还可能不取。
B国的人不去向常规考虑奇偶分组,这个会在后面提到。
题意抽象为求一个最大完全图,那么当我们确定一个极大完全图后,任意一个元素都可以作为代表元,给定代表元之后,通过一边O(n)的扫描就能得到这个极大完全图。
所以对于不含A国人的情况,我们只需要枚举一个B国人,把其他的B国人尽量多的加进去,这个加人的顺序与结果无关,而代表元可以使任意一个,因此可以用一个数组记录v[x]表示是否求过以x为代表元的集合。
对于有A国人的情况,枚举一个A国人,再枚举一个B国人,同理他们构成的最大完全图也就确定了,同样可以使用记忆化来降低枚举时间。
对于两个A国人的情况,一样处理即可。
程序有两个记录数组v1,v2,由于A,B的人数差距极大,用一个数组记录就需要开10*10*1500,但是事实上的数据会达到200*200*3000,极大的超内存,所以采用分开处理的方式,A较小B较大时用200*200*200的数组,A极小B很大时用50*50*3000的,内存就很充裕了。
而对于时间复杂度,为最大枚举数O(sa*sa*sb*sb),加入的v数组会让它达不到这个极限。
事实证明,时限为20S的题目,我的程序通过最大点的时间仅为2s++
如有反例,欢迎提出。
View Code
program friends(input,output); var can:array[0..4050,0..4050] of boolean; a:array[0..1005] of longint; b:array[0..4010] of longint; stack:array[0..600] of longint; v1:array[0..310,0..310,0..400] of boolean; v2:array[0..50,0..50,0..3600] of boolean; flag:boolean; top:longint; answer:longint; sa,sb,m:longint; cases:longint; function check(x:longint):boolean; var i,sum:longint; begin sum:=0; for i:=0 to 30 do if (x and (1 shl i))>0 then inc(sum); if odd(sum) then exit(true); exit(false); end;{ check } procedure init; var i,j,xx,yy:longint; begin readln(sa,sb,m); if (sa<=300)and(sb<=350) then flag:=true; if (sa<=20)and(sb<=3000) then flag:=false; fillchar(can,sizeof(can),false); for i:=1 to sa do read(a[i]); for i:=1 to sb do read(b[i]); for i:=1 to m do begin read(xx,yy); can[xx,yy+sa]:=true; can[yy+sa,xx]:=true; end; for i:=1 to sa-1 do for j:=i+1 to sa do if ((a[i] xor a[j]) mod 2=1) then begin can[i,j]:=true; can[j,i]:=true; end; for i:=1 to sb-1 do for j:=i+1 to sb do if ((b[i] xor b[j]) mod 2=0)or(check(b[i] or b[j])) then begin can[i+sa,j+sa]:=true; can[j+sa,i+sa]:=true; end; fillchar(v1,sizeof(v1),false); fillchar(v2,sizeof(v2),false); for i:=0 to sa+sb do begin can[0,i]:=true; can[i,0]:=true; end; end;{ init } procedure calc(xx,yy,zz:longint); var i,j:longint; flags:boolean; begin top:=0; if xx<>0 then begin inc(top); stack[top]:=xx; end; if yy<>0 then begin inc(top); stack[top]:=yy; end; if zz<>sa then begin inc(top); stack[top]:=zz; end; if flag then v1[xx,yy,zz-sa]:=true else v2[xx,yy,zz-sa]:=true; for i:=1 to sb do if (i+sa<>zz) then begin flags:=true; for j:=top downto 1 do if not can[i+sa,stack[j]] then begin flags:=false; break; end; if not flags then continue; inc(top); stack[top]:=sa+i; if flag then v1[xx,yy,i]:=true else v2[xx,yy,i]:=true end; if top>answer then answer:=top; end;{ calc } procedure main; var i,j,k:longint; begin answer:=0; if sa=0 then begin for i:=1 to sb do calc(0,0,i); exit; end; if sa=1 then begin for i:=0 to 1 do for j:=sa+1 to sb+sa do if (((not v1[0,i,j-sa])and(flag))or((not flag)and(not v2[0,i,j-sa])))and(can[i,j]) then calc(0,i,j); exit; end; for i:=sa+1 to sb+sa do calc(0,0,i); for i:=0 to sa-1 do for j:=i+1 to sa do if can[i,j] then for k:=sa+1 to sb+sa do if (((not v1[i,j,k-sa])and(flag))or((not flag)and(not v2[i,j,k-sa])))and(can[i,k])and(can[j,k]) then calc(i,j,k); end;{ main } procedure print; begin writeln(answer); end;{ print } begin assign(input,'friends.in');reset(input); assign(output,'friends.out');rewrite(output); readln(cases); while cases>0 do begin dec(cases); init; main; print; end; close(input); close(output); end.
注:BZOJ上仅有一组数据且输入没有T,直接按一组数据做即可。
本随笔为原创,如要转载,请注明出处。
相关文章推荐
- bzoj2744【HEOI2012】朋友圈
- 【BZOJ2744】【二分图】[HEOI2012]朋友圈 题解
- [HEOI2012][BZOJ2744] 朋友圈|匈牙利算法|最大独立集|最大团
- BZOJ 2744: [HEOI2012]朋友圈
- 【bzoj2744】[HEOI2012]朋友圈 二分图匹配
- [BZOJ]2744: [HEOI2012]朋友圈 二分图匹配
- HEOI2012 朋友圈
- bzoj 2744: [HEOI2012]朋友圈 (二分图最大团)
- 【最大团转最大点独立集(匈牙利算法+时间戳优化)】BZOJ2744-[HEOI2012]朋友圈
- bzoj2744 [HEOI2012]朋友圈 二分图大匹配——最大独立集
- bzoj 2744: [HEOI2012]朋友圈 网络流
- 【BZOJ 2744 】[HEOI2012]朋友圈
- BZOJ 2744: [HEOI2012]朋友圈
- BZOJ2744: [HEOI2012]朋友圈
- 【BZOJ 2744】【HEOI2012】朋友圈
- BZOJ2744 HEOI2012朋友圈(二分图匹配)
- 【BZOJ】【LYDSY】【大视野】2744(【HEOI2012】)朋友圈
- bzoj2744 [HEOI2012]朋友圈 ( 二分图最大团转补图最大独立集+时间戳优化+匈牙利算法)
- BZOJ 2744 HEOI2012 朋友圈 二分图最大匹配
- HEOI2012 朋友圈