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,直接按一组数据做即可。

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

     

  • 相关阅读:
    hdu 5119 Happy Matt Friends
    hdu 5128 The E-pang Palace
    hdu 5131 Song Jiang's rank list
    hdu 5135 Little Zu Chongzhi's Triangles
    hdu 5137 How Many Maos Does the Guanxi Worth
    hdu 5122 K.Bro Sorting
    Human Gene Functions
    Palindrome(最长公共子序列)
    A Simple problem
    Alignment ( 最长上升(下降)子序列 )
  • 原文地址:https://www.cnblogs.com/neverforget/p/2493995.html
Copyright © 2011-2022 走看看