BZOJ 3275: Number 最小割
2017-05-27 16:45
381 查看
3275: Number
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1057 Solved: 439
[Submit][Status][Discuss]
Description
有N个正整数,需要从中选出一些数,使这些数的和最大。若两个数a,b同时满足以下条件,则a,b不能同时被选
1:存在正整数C,使a*a+b*b=c*c
2:gcd(a,b)=1
Input
[align=left]第一行一个正整数n,表示数的个数。[/align][align=left]第二行n个正整数a1,a2,?an。[/align]
[align=left] [/align]
Output
[align=left]最大的和。[/align][align=left] [/align]
Sample Input
53 4 5 6 7
Sample Output
22HINT
n<=3000。最小割
可以证明奇数和奇数(不能构成勾股数)、偶数和偶数(最大公因数一定不会是1)是一定可以共存的,所以有可能连边的只可能是奇数和偶数之间所以只要枚举判断每两个奇数和偶数之间能否连边即可
当出现不能同时存在的情况时连一条inf的边即可
#include<cmath> #include<ctime> #include<cstdio> #include<cstdlib> #include<cstring> #include<complex> #include<iostream> #include<algorithm> #include<iomanip> #include<vector> #include<string> #include<queue> #include<set> #include<map> using namespace std; typedef long long ll; inline ll read() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return f*x; } const int N=3100;const ll inf=0X7f7f7f7f7f7f7fll; int last ,ecnt=1,even ,odd ,q ,d ,S=0,T=N-1; ll ans,a ,n; struct EDGE{int to,nt;ll val;}e[1200010]; inline void readd(int u,int v,ll val) {e[++ecnt]=(EDGE){v,last[u],val};last[u]=ecnt;} inline void add(int u,int v,ll val) {readd(u,v,val);readd(v,u,0);} int gcd(int x,int y){return y==0?x:gcd(y,x%y);} bool bfs() { memset(d,0,sizeof(d)); int head=0,tail=1;d[S]=1;q[head]=S; while(head<tail) { int u=q[head++]; for(int i=last[u];i;i=e[i].nt) if(e[i].val&&!d[e[i].to]) { d[e[i].to]=d[u]+1; q[tail++]=e[i].to; } }//cout<<d[T]<<endl; return d[T]; } ll dfs(int u,ll lim) { if(u==T||!lim)return lim; ll flow=0; for(int i=last[u];i;i=e[i].nt) if(d[e[i].to]==d[u]+1) { ll tmp=dfs(e[i].to,min(lim,e[i].val)); e[i].val-=tmp;e[i^1].val+=tmp;lim-=tmp;flow+=tmp; if(!lim)break; } if(!flow)d[u]=-1; return flow; } void dinic() {while(bfs())ans+=dfs(S,inf);} int main() { ll n=read();ll sum=0; for(int i=1;i<=n;i++) { a[i]=read();sum+=a[i]; if(a[i]&1)add(S,i,a[i]),odd[++odd[0]]=i; else add(i,T,a[i]),even[++even[0]]=i; } for(int i=1;i<=odd[0];i++) for(int j=1;j<=even[0];j++) { ll tmp=a[odd[i]]*a[odd[i]]+a[even[j]]*a[even[j]];ll t=sqrt(tmp); if(t*t==tmp&&gcd(a[odd[i]],a[even[j]])==1)add(odd[i],even[j],inf); } dinic(); printf("%lld\n",sum-ans); return 0; } /* 5 3 4 5 6 7 Sample Output 22 */
相关文章推荐
- BZOJ3275 Number-最小割
- [BZOJ3275]Number(最小割)
- bzoj 3275: Number 最小割
- BZOJ3275 Number (最小割)
- BZOJ 3275: Number( 最小割 )
- 【bzoj3275】Number 最小割
- bzoj 3275: Number (最小割)
- 【最小割】【Dinic】bzoj3275 Number
- BZOJ 3275 Number 最小割
- 【bzoj 3275】Number(最小割)
- BZOJ 3275 Number && 3158 千钧一发 最小割
- 【BZOJ3275】Number 最小割
- bzoj 3275 Number(最小割)
- bzoj3275 Number
- bzoj3275 Number(最大点权独立集)
- bzoj 3275: Number
- bzoj3275 Number
- bzoj3275: Number
- BZOJ3275 Number
- bzoj3275 Number