zoukankan      html  css  js  c++  java
  • 【BZOJ3275】Number 最小割

    【BZOJ3275】Number

    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

    Sample Output

    22

    HINT

    n<=3000。

    题解:先是无脑码了个最小割,果断WA了,看网上才又get了一个新定理

    易证:奇数和奇数的平方和一定不是完全平方数,偶数和偶数的gcd一定不为1

    然后就把所有的数分成奇数和偶数两个集合,然后再跑最小割就完事了

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <queue>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    int n,cnt,tot,ans,tx,ty;
    queue<int> q;
    int vx[3010],vy[3010],next[1000000],head[6010],to[1000000],val[1000000],d[6010];
    int gcd(int a,int b)
    {
    	return (b==0)?a:gcd(b,a%b);
    }
    int dfs(int x,int mf)
    {
    	if(x==n+1)	return mf;
    	int i,k,temp=mf;
    	for(i=head[x];i!=-1;i=next[i])
    	{
    		if(d[to[i]]==d[x]+1&&val[i])
    		{
    			k=dfs(to[i],min(temp,val[i]));
    			if(!k)	d[to[i]]=0;
    			val[i]-=k,val[i^1]+=k,temp-=k;
    			if(!temp)	break;
    		}
    	}
    	return mf-temp;
    }
    int bfs()
    {
    	int i,u;
    	memset(d,0,sizeof(d));
    	while(!q.empty())	q.pop();
    	q.push(0),d[0]=1;
    	while(!q.empty())
    	{
    		u=q.front(),q.pop();
    		for(i=head[u];i!=-1;i=next[i])
    		{
    			if(!d[to[i]]&&val[i])
    			{
    				d[to[i]]=d[u]+1;
    				if(to[i]==n+1)	return 1;
    				q.push(to[i]);
    			}
    		}
    	}
    	return 0;
    }
    void add(int a,int b,int c)
    {
    	to[cnt]=b;
    	val[cnt]=c;
    	next[cnt]=head[a];
    	head[a]=cnt++;
    }
    int main()
    {
    	scanf("%d",&n);
    	int i,j,k;
    	memset(head,-1,sizeof(head));
    	for(i=1;i<=n;i++)
    	{
    		scanf("%d",&k);
    		tot+=k;
    		if(k&1)	vx[++tx]=k;
    		else	vy[++ty]=k;
    	}
    	for(i=1;i<=tx;i++)	add(0,i,vx[i]),add(i,0,0);
    	for(i=1;i<=ty;i++)	add(i+tx,n+1,vy[i]),add(n+1,i+tx,0);
    	for(i=1;i<=tx;i++)
    	{
    		for(j=1;j<=ty;j++)
    		{
    			if(gcd(vx[i],vy[j])!=1)	continue;
    			int k=vx[i]*vx[i]+vy[j]*vy[j];
    			if(int(sqrt(k*1.0)+0.00001)*int(sqrt(k*1.0)+0.00001)==k)
    			{
    				add(i,tx+j,1<<30);
    				add(tx+j,i,0);
    			}
    		}
    	}
    	while(bfs())	ans+=dfs(0,1<<30);
    	printf("%d",tot-ans);
    	return 0;
    }
  • 相关阅读:
    极简的js点击组图切换效果
    原生js登录创建cookie
    原生js的表单验证
    Inno Setup 检测已安装的.NET Framework 版本
    IntelliJ IDEA中创建并运行scala应用程序
    解决eclipse中maven出现的Failure to transfer XXX.jar的问题
    初识python yield
    解决pycharm无法导入本地包的问题(Unresolved reference 'tutorial')
    理解Python的with as语句
    scrapy写爬虫是出现no module named win32api错误
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/6442188.html
Copyright © 2011-2022 走看看