BZOJ2661 连连看 (费用流)
把所有点拆成两个,将符合条件的两个点x,y连上边,流量为1,费用为-(x+y)。
做一遍最小费用最大流,最后ans div 2即可。
1 Program bzoj2661; 2 const INF=2000000000; 3 var last,next,p,cost,cap,q:array[0..1000000] of longint; 4 flag1,flag2:array[0..10000] of boolean; 5 a,c,i,j,x,y,t,s,sum:longint; 6 b:array[0..1000000] of longint; 7 pd:array[0..10000] of boolean; 8 d,ps:array[0..10000] of longint; 9 function gcd(x,y:longint):longint; 10 begin 11 if y=0 then exit(x) else exit(gcd(y,x mod y)); 12 end; 13 procedure add(x,y,f,c:longint); 14 begin 15 inc(sum); next[sum]:=last[x]; last[x]:=sum; 16 p[sum]:=y; q[sum]:=x; cost[sum]:=c; cap[sum]:=f; 17 end; 18 procedure adt(x,y,f,c:longint); 19 begin 20 add(x,y,f,c); add(y,x,0,-c); 21 end; 22 procedure spfa; 23 var i,j,l,r:longint; 24 begin 25 for i:=0 to t do d[i]:=INF; 26 fillchar(pd,sizeof(pd),false); 27 l:=1; r:=1; pd[s]:=true; b[1]:=s; d[s]:=0; 28 while l<=r do 29 begin 30 i:=last[b[l]]; 31 while i<>0 do 32 begin 33 if (cap[i]>0) and (d[p[i]]>d[b[l]]+cost[i]) then 34 begin 35 d[p[i]]:=d[b[l]]+cost[i]; 36 ps[p[i]]:=i; 37 if not pd[p[i]] then 38 begin 39 inc(r); 40 b[r]:=p[i]; 41 pd[p[i]]:=true; 42 end; 43 end; 44 i:=next[i]; 45 end; 46 pd[b[l]]:=false; 47 inc(l); 48 end; 49 end; 50 procedure minCmaxF; 51 var x,i,j,cc,f,min:longint; 52 begin 53 f:=0; cc:=0; 54 while true do 55 begin 56 spfa; 57 if d[t]=INF then 58 begin 59 writeln(f div 2,' ',-cc div 2); 60 exit; 61 end; 62 min:=INF; 63 x:=t; 64 while x<>s do 65 begin 66 if cap[ps[x]]<min then min:=cap[ps[x]]; 67 x:=q[ps[x]]; 68 end; 69 x:=t; 70 while x<>s do 71 begin 72 dec(cap[ps[x]],min); 73 inc(cap[ps[x] xor 1],min); 74 x:=q[ps[x]]; 75 end; 76 cc:=cc+min*d[t]; 77 f:=f+min; 78 end; 79 end; 80 begin 81 readln(a,c); 82 s:=0; 83 for i:=a to c do 84 for j:=a to c do if (i<>j) then 85 begin 86 x:=trunc(sqrt(abs(i*i-j*j))); 87 if x*x<>abs(i*i-j*j) then continue; 88 if gcd(i,j)<>1 then continue; 89 add(i,j+c,1,-(i+j)); 90 end; 91 for i:=a to c do add(0,i,1,0); 92 for i:=a to c do add(i+c,c*2+1,1,0); 93 s:=0; t:=2*c+1; 94 minCmaxF; 95 end.