3275: Number
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 892 Solved: 383
[Submit][Status][Discuss]
Description
有N个正整数,需要从中选出一些数,使这些数的和最大。
若两个数a,b同时满足以下条件,则a,b不能同时被选
1:存在正整数C,使a*a+b*b=c*c
2:gcd(a,b)=1
Input
第一行一个正整数n,表示数的个数。
第二行n个正整数a1,a2,?an。
Output
最大的和。
Sample Input
5
3 4 5 6 7
3 4 5 6 7
Sample Output
22
HINT
n<=3000。
题解
首先观察出可以把数字按奇数和偶数变成二分图,因为第一条性质保证了奇数和奇数之间没有边(奇数的平方和模4余2,而是偶数的平方数是4的倍数),第二条性质保证了偶数和偶数之间没有边。然后把奇数连s,偶数连T,容量是权值;奇数和偶数之间满足条件就连容量无穷打的边。这样最后答案要保证选出来的点组成的子图中S到T不连通,所以割某条边就相当于这个数不在集合里,最大化选的点的圈就是最小化割的权。最后所有点的权和减去最小割就行。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 program j01; 2 const maxn=3006;maxm=1000086; 3 var flow,next,q:array[0..maxm]of longint; 4 head:array[0..maxn]of longint; 5 dis,l,a:array[0..maxn]of longint; 6 s,t,tt,n,i,j:longint; 7 ans:int64; 8 9 procedure add(u,v,w:longint); 10 begin 11 inc(tt);q[tt]:=v;next[tt]:=head[u];head[u]:=tt;flow[tt]:=w; 12 end; 13 14 function min(a,b:longint):longint; 15 begin 16 if a<b then exit(a) else exit(b); 17 end; 18 19 function gcd(a,b:longint):longint; 20 begin 21 if b=0 then exit(a) else exit(gcd(b,a mod b)); 22 end; 23 24 function jud(a,b:int64):boolean; 25 var tmp,m:int64; 26 begin 27 tmp:=a*a+b*b; 28 m:=trunc(sqrt(tmp)); 29 exit(m*m=tmp); 30 end; 31 32 function bfs:boolean; 33 var h,tail,i,j:longint; 34 begin 35 h:=0;tail:=1;l[1]:=s; 36 fillchar(dis,sizeof(dis),$3f);dis[s]:=0; 37 while h<>tail do 38 begin 39 inc(h);i:=l[h];j:=head[i]; 40 while j>0 do 41 begin 42 if (dis[i]+1<dis[q[j]])and(flow[j]>0) then 43 begin 44 dis[q[j]]:=dis[i]+1; 45 inc(tail);l[tail]:=q[j]; 46 end; 47 j:=next[j]; 48 end; 49 end; 50 if dis[t]=$3f3f3f3f then exit(false) else exit(true); 51 end; 52 53 function dfs(i,ll:longint):longint; 54 var j,x,tmp:longint; 55 begin 56 if i=t then exit(ll); 57 j:=head[i];x:=0; 58 while j>0 do 59 begin 60 if (dis[q[j]]=dis[i]+1)and(flow[j]>0) then 61 begin 62 tmp:=dfs(q[j],min(ll-x,flow[j])); 63 dec(flow[j],tmp); 64 inc(flow[j xor 1],tmp); 65 inc(x,tmp); 66 if x=ll then exit(x); 67 end; 68 j:=next[j]; 69 end; 70 if x=0 then dis[i]:=-1; 71 exit(x); 72 end; 73 74 begin 75 readln(n); 76 s:=0;t:=n+1;tt:=1;ans:=0; 77 for i:=1 to n do 78 begin 79 read(a[i]);ans:=ans+a[i]; 80 if a[i] mod 2=1 then 81 begin 82 add(s,i,a[i]);add(i,s,0); 83 end else 84 begin 85 add(i,t,a[i]);add(t,i,0); 86 end; 87 end; 88 for i:=1 to n do 89 if a[i] mod 2=1 then 90 for j:=1 to n do 91 if a[j] mod 2=0 then 92 if (gcd(a[i],a[j])=1)and jud(a[i],a[j]) then 93 begin 94 add(i,j,maxlongint); 95 add(j,i,0); 96 end; 97 while bfs do 98 ans:=ans-dfs(s,maxlongint); 99 writeln(ans); 100 end.