zoukankan      html  css  js  c++  java
  • HEOI2012 朋友圈

    这是做的最得意的一道题,当时在考场上得了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
      1 program friends(input,output);
      2 var
      3     can:array[0..4050,0..4050] of boolean;
      4     a:array[0..1005] of longint;
      5     b:array[0..4010] of longint;
      6     stack:array[0..600] of longint;
      7     v1:array[0..310,0..310,0..400] of boolean; 
      8     v2:array[0..50,0..50,0..3600] of boolean;
      9     flag:boolean;
     10     top:longint;
     11     answer:longint;
     12     sa,sb,m:longint;
     13     cases:longint;
     14 function check(x:longint):boolean;
     15 var
     16     i,sum:longint;
     17 begin
     18     sum:=0;
     19     for i:=0 to 30 do
     20         if (x and (1 shl i))>0 then
     21             inc(sum);
     22     if odd(sum) then
     23         exit(true);
     24     exit(false);
     25 end;{ check }
     26 procedure init;
     27 var
     28     i,j,xx,yy:longint;
     29 begin
     30     readln(sa,sb,m);
     31     if (sa<=300)and(sb<=350) then
     32         flag:=true;
     33     if (sa<=20)and(sb<=3000) then
     34         flag:=false;
     35     fillchar(can,sizeof(can),false);
     36     for i:=1 to sa do
     37         read(a[i]);
     38     for i:=1 to sb do
     39         read(b[i]);
     40     for i:=1 to m do
     41     begin
     42         read(xx,yy);
     43         can[xx,yy+sa]:=true;
     44         can[yy+sa,xx]:=true;
     45     end;
     46     for i:=1 to sa-1 do
     47         for j:=i+1 to sa do
     48             if ((a[i] xor a[j]) mod 2=1) then
     49             begin
     50                 can[i,j]:=true;
     51                 can[j,i]:=true;
     52             end;
     53     for i:=1 to sb-1 do
     54         for j:=i+1 to sb do
     55             if ((b[i] xor b[j]) mod 2=0)or(check(b[i] or b[j])) then
     56             begin
     57                 can[i+sa,j+sa]:=true;
     58                 can[j+sa,i+sa]:=true;
     59             end;
     60     fillchar(v1,sizeof(v1),false);
     61     fillchar(v2,sizeof(v2),false);
     62     for i:=0 to sa+sb do
     63     begin
     64         can[0,i]:=true;
     65         can[i,0]:=true;
     66     end;
     67 end;{ init }
     68 procedure calc(xx,yy,zz:longint);
     69 var
     70     i,j:longint;
     71     flags:boolean;
     72 begin
     73     top:=0;
     74     if xx<>0 then
     75     begin
     76         inc(top);
     77         stack[top]:=xx;
     78     end;
     79     if yy<>0 then
     80     begin    
     81         inc(top);
     82         stack[top]:=yy;
     83     end;
     84     if zz<>sa then
     85     begin
     86         inc(top);
     87         stack[top]:=zz;
     88     end;
     89     if flag then
     90         v1[xx,yy,zz-sa]:=true
     91     else
     92         v2[xx,yy,zz-sa]:=true;
     93     for i:=1 to sb do
     94         if (i+sa<>zz) then
     95         begin
     96             flags:=true;
     97             for j:=top downto 1 do
     98                 if not can[i+sa,stack[j]] then
     99                 begin
    100                     flags:=false;
    101                     break;
    102                 end;
    103             if not flags then
    104                 continue;
    105             inc(top);
    106             stack[top]:=sa+i;
    107             if flag then
    108                 v1[xx,yy,i]:=true
    109             else
    110                 v2[xx,yy,i]:=true
    111         end;
    112     if top>answer then
    113         answer:=top;
    114 end;{ calc }
    115 procedure main;
    116 var
    117     i,j,k:longint;
    118 begin
    119     answer:=0;
    120     if sa=0 then
    121     begin
    122         for i:=1 to sb do
    123             calc(0,0,i);
    124         exit;
    125     end;
    126     if sa=1 then
    127     begin
    128         for i:=0 to 1 do
    129             for j:=sa+1 to sb+sa do
    130                 if (((not v1[0,i,j-sa])and(flag))or((not flag)and(not v2[0,i,j-sa])))and(can[i,j]) then
    131                     calc(0,i,j);
    132         exit;
    133     end;
    134     for i:=sa+1 to sb+sa do
    135         calc(0,0,i);
    136     for i:=0 to sa-1 do
    137         for j:=i+1 to sa do
    138             if can[i,j] then
    139             for k:=sa+1 to sb+sa do
    140                 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
    141                     calc(i,j,k);
    142 end;{ main }
    143 procedure print;
    144 begin
    145     writeln(answer);
    146 end;{ print }
    147 begin
    148     assign(input,'friends.in');reset(input);
    149     assign(output,'friends.out');rewrite(output);
    150     readln(cases);
    151     while cases>0 do
    152     begin
    153         dec(cases);
    154         init;
    155         main;
    156         print;
    157     end;
    158     close(input);
    159     close(output);
    160 end.

     

    注:BZOJ上仅有一组数据且输入没有T,直接按一组数据做即可。

    本随笔为原创,如要转载,请注明出处。

     

  • 相关阅读:
    IDEA中项目编码格式设置
    font awesome 页面小图标
    ffmpeg无损MP4转TS 及bat批量脚本
    Mysql超百万数据的导入导出
    查询流水表中所有用户最后一条和第一条记录
    css样式实现网页全黑白
    jsp中二维码展示及异步轮询查询
    支付宝当面付对接
    微信native支付对接
    Java和python实现斐波那契数列的感触
  • 原文地址:https://www.cnblogs.com/neverforget/p/2493995.html
Copyright © 2011-2022 走看看