bzoj 3275: Number (最小割)

题目的意思是要选一些数,但是这些数如果满足两个条件的话就不能一起被选。

 

 

 

type
  arr=record
    toward,next,cap:longint;
  end;
 
const
  maxn=4000;
  maxm=300000;
var
  gap,first,cur,d,num1,num2:array[0..maxn]of longint;
  edge:array[0..maxm]of arr;
  tot,s,t,n,esum,sum:longint;
 
 
function min(x,y:longint):longint;
begin
  if x<y then exit(x);
  exit(y);
end;
 
procedure add(j,k,l:longint);
begin
  //writeln(j,' ',k,' ',l);
  inc(esum);
  edge[esum].toward:=k;
  edge[esum].next:=first[j];
  first[j]:=esum;
  edge[esum].cap:=l;
end;
 
procedure addedge(j,k,l:longint);
begin
  add(j,k,l);
  add(k,j,0);
end;
 
function sap(x,flow:longint):longint;
var
  i,too,more,now:longint;
begin
  if x=t then exit(flow);
  now:=0;
  i:=cur[x];
  while i>=0 do begin
    too:=edge[i].toward;
    if (d[x]=d[too]+1) and (edge[i].cap>0) then begin
      more:=sap(too,min(edge[i].cap,flow-now));
      dec(edge[i].cap,more);
      inc(edge[i xor 1].cap,more);
      inc(now,more);
      cur[x]:=i;
      if flow=now then exit(flow);
    end;
    i:=edge[i].next;
  end;
  dec(gap[d[x]]);
  if gap[d[x]]=0 then d[s]:=tot;
  inc(d[x]);
  inc(gap[d[x]]);
  cur[x]:=first[x];
  exit(now);
end;
 
function maxflow:longint;
var
  i,ans:longint;
begin
  fillchar(d,sizeof(d),0);
  fillchar(gap,sizeof(gap),0);
  gap[0]:=tot;
  for i:=1 to tot do cur[i]:=first[i];
  ans:=0;
  while d[s]<tot do
    inc(ans,sap(s,maxlongint));
  exit(ans);
end;
 
function gcd(x,y:longint):boolean;
begin
  if y=0 then exit(x=1);
  exit(gcd(y,x mod y));
end;
 
procedure into;
var
  i,j,tot1,tot2,k:longint;
begin
  readln(n);
  esum:=-1;
  fillchar(first,sizeof(first),255);
  tot1:=0;
  tot2:=0;
  for i:=1 to n do begin
    read(j);
    if j and 1=1 then begin
      inc(tot1);
      num1[tot1]:=j;
    end
    else begin
      inc(tot2);
      num2[tot2]:=j;
    end;
    inc(sum,j);
  end;
  for i:=1 to tot1 do
    for j:=1 to tot2 do
      if gcd(num1[i],num2[j]) then begin
        k:=sqr(num1[i])+sqr(num2[j]);
        if sqr(trunc(sqrt(k)))=k then addedge(i,j+tot1,maxlongint);
      end;
 // writeln;
  tot:=tot1+tot2+2;
  s:=tot-1;
  t:=tot;
  for i:=1 to tot1 do addedge(s,i,num1[i]);
  for i:=1 to tot2 do addedge(i+tot1,t,num2[i]);
 { for i:=1 to tot1 do writeln(i,' ',num1[i]);
  for i:=1 to tot2 do writeln(i,' ',num2[i]); }
end;
 
begin
  into;
  writeln(sum-maxflow);
  readln;
  readln;
end.
View Code

 

posted @ 2015-03-22 21:53  Macaulish  阅读(174)  评论(0编辑  收藏  举报