版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/qq_35950004/article/details/88430419
题目
首先这个题是二元关系,我们想到了最小割。
最大值转化为总值-最小割,于是关系变为两者同时选时代价+inf。
相同>相异。需要反转,需要二分图环境。
考虑小学奥数
猜想满足条件的数奇偶性不同。
同偶:gcd = 2
同奇:考虑
意义下
矛盾。
于是奇偶性不同的才会连边,我们把偶数的S边,T边交换即可。
反转成功。
AC Code:
#include<bits/stdc++.h>
#define maxn 3005
#define maxm 1000006
#define LL int
#define inf 0x3f3f3f3f
using namespace std;
int n,a[maxn];
int info[maxn],to[maxm],Prev[maxm],cap[maxm],cnt_e=1;
void Node(int u,int v,int c){ Prev[++cnt_e]=info[u],info[u]=cnt_e,to[cnt_e]=v,cap[cnt_e]=c; }
void Line(int u,int v,int c){ Node(u,v,c),Node(v,u,0); }
int b[2][maxn],cnt[2],dis[maxn],S,T;
inline int gcd(int a,int b){ return !b ? a : gcd(b,a%b); }
int aug(int now,int Max)
{
if(now == T) return Max;
int inc , st = Max;
for(int i=info[now];i;i=Prev[i])
if(cap[i] && dis[to[i]] + 1 == dis[now])
{
inc = aug(to[i] , min(cap[i] , st));
if(!inc) dis[to[i]] = -1;
else st-=inc,cap[i]-=inc,cap[i^1]+=inc;
if(!st) break;
}
return Max - st;
}
bool BFS()
{
static queue<int>q;
memset(dis,-1,sizeof dis);
q.push(T),dis[T] = 0;
for(int now;!q.empty();)
{
now = q.front() , q.pop();
for(int i=info[now];i;i=Prev[i])
if(cap[i^1] && dis[to[i]] == -1)
{
dis[to[i]] = dis[now] + 1;
q.push(to[i]);
}
}
return dis[S] != -1;
}
int main()
{
scanf("%d",&n);
LL ans = 0;
S = n + 1 , T = n + 2;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
ans += a[i];
if(!(a[i]&1)) Line(S,i,a[i]),b[0][++cnt[0]] = i;
else Line(i,T,a[i]),b[1][++cnt[1]] = i;
}
for(int i=1;i<=cnt[0];i++)
for(int j=1;j<=cnt[1];j++)
if(gcd(a[b[0][i]],a[b[1][j]])==1){
LL tmp = sqrt(a[b[0][i]]*a[b[0][i]]+a[b[1][j]]*a[b[1][j]]);
if(tmp * tmp == a[b[0][i]]*a[b[0][i]]+a[b[1][j]]*a[b[1][j]])
{
Line(b[0][i],b[1][j],inf);
}
}
for(;BFS();)
ans -= aug(S,inf);
printf("%d\n",ans);
}