最小割。
网络流不要写错。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#define maxn 5050
#define maxv 20050
#define maxe 400050
#define inf 1000000007
using namespace std;
int n,a[maxn],nume=1,g[maxv],s,t,dis[maxv];
queue <int> q;
struct edge
{
int v,f,nxt;
}e[maxe];
void addedge(int u,int v,int f)
{
e[++nume].v=v;
e[nume].f=f;
e[nume].nxt=g[u];
g[u]=nume;
e[++nume].v=u;
e[nume].f=0;
e[nume].nxt=g[v];
g[v]=nume;
}
int gcd(int a,int b)
{
if (b==0) return a;
return gcd(b,a%b);
}
bool judge(int x,int y)
{
int nowx=a[x],nowy=a[y];
int ans=nowx*nowx+nowy*nowy;
ans=sqrt(ans);
if ((ans*ans==nowx*nowx+nowy*nowy) && (gcd(nowx,nowy)==1))
return true;
return false;
}
bool bfs()
{
queue <int> q;
memset(dis,-1,sizeof(dis));
int vis[maxv];
memset(vis,0,sizeof(vis));
vis[0]=1;
q.push(0);
while (!q.empty())
{
int head=q.front();
q.pop();
for (int i=g[head];i;i=e[i].nxt)
{
if ((e[i].f) && (vis[e[i].v]==0))
{
q.push(e[i].v);
dis[e[i].v]=dis[head]+1;
vis[e[i].v]=1;
}
}
}
if (dis[t]==-1) return false;
return true;
}
int dinic(int x,int low)
{
if (x==t)
return low;
else
{
int ret=0;
for (int i=g[x];low && i;i=e[i].nxt)
{
if (e[i].f && dis[e[i].v]==dis[x]+1)
{
int dd=dinic(e[i].v,min(e[i].f,low));
e[i].f=e[i].f-dd;
e[i^1].f=e[i^1].f+dd;
low=low-dd;
ret=ret+dd;
}
}
if (ret==0) dis[x]=-1;
return ret;
}
}
int main()
{
int sum=0;
scanf("%d",&n);
s=0;t=2*n+1;
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
addedge(s,i,a[i]);
addedge(n+i,t,a[i]);
sum=sum+a[i];
}
for (int i=1;i<=n;i++)
for (int j=i+1;j<=n;j++)
{
if (judge(i,j)==true)
{
addedge(i,n+j,inf);
addedge(j,n+i,inf);
}
}
int min_cut=0;
while (bfs()==true)
min_cut=min_cut+dinic(s,inf);
printf("%d\n",sum-min_cut/2);
return 0;
}