Minimum cut.
Network flow don't write wrong.
#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;
}
Bzoj 3275 Number