zoukankan      html  css  js  c++  java
  • 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+re21次……我服了

    这题网络流是显然的,但是我觉得直接拆点建图6000点就是7200w边会T

    然后orz了黄巨大,其实直接建图也不会T,而且根本不用拆点

    就是先把所有点奇偶分离。可以证明奇数和奇数、偶数和偶数是不行的

    有个推论是:如果a、b是任意奇数,c是任意数,不存在c^2=a^2+b^2 (证明我不会,求大神指教)

    所以奇数不满足1性质

    然后偶数显然不满足2性质

    所以S向所有奇数连权值为a[i]的边,所有偶数向T连权值为a[i]的边,奇偶之间不能同时被选的连inf的边,求一下最小割

    因为是网络流,保证取的是互斥的两个数中最小的。所以这样是可行的

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    #define inf 1000000000
    #define S 0
    #define T (n+1)
    #define N 5010
    struct edge{
    	int to,next,v;
    }e[500010];
    int q[N];
    int head[N],h[N],cur[N];
    int lt[N],rt[N],a[N];
    int n,ll,rl,cnt=1,ans,tot;
    inline void swap(int &a,int &b){int t=a;a=b;b=t;}
    inline int min(int a,int b){return a<b?a:b;}
    inline void ins(int u,int v,int w)
    {
    	e[++cnt].to=v;
    	e[cnt].v=w;
    	e[cnt].next=head[u];
    	head[u]=cnt;
    }
    inline void insert(int u,int v,int w)
    {
    	ins(u,v,w);
    	ins(v,u,0);
    }
    inline int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
    inline bool jud(int a,int b)
    {
    	if (a<b)swap(a,b);
    	int s=a*a+b*b,t=(int)sqrt(s);
    	return t*t==s&&gcd(a,b)==1;
    }
    inline bool bfs()  
    {  
        memset(h,-1,sizeof(h));  
        int t=0,w=1;  
        q[1]=S;h[S]=0;  
        while (t<w)  
        {  
            int now=q[++t];  
            for (int i=head[now];i;i=e[i].next)  
              if(h[e[i].to]==-1&&e[i].v)  
              {  
                q[++w]=e[i].to;  
                h[e[i].to]=h[now]+1;  
              }  
        }  
        if (h[T]==-1) return 0;  
        return 1;  
    }  
    inline int dfs(int x,int f)  
    {  
        if (x==T||!f) return f;  
        int used=0,w;  
        for (int i=head[x];i;i=e[i].next)  
          if (e[i].v&&h[e[i].to]==h[x]+1)  
          {  
            w=f-used;  
            w=dfs(e[i].to,min(e[i].v,w));  
            used+=w;  
            e[i].v-=w;  
            e[i^1].v+=w;
            if (used==f)return f;
          }  
        if (!used) h[x]=-1;  
        return used;  
    }  
    inline void dinic(){while(bfs())ans+=dfs(S,inf);}
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int main()
    {
    	n=read();
    	for (int i=1;i<=n;i++)
    	{
    		a[i]=read();tot+=a[i];
    		if (a[i]%2==1)
    		{
    			lt[++ll]=i;
    			insert(S,i,a[i]);
    		}else
    		{
    			rt[++rl]=i;
    			insert(i,T,a[i]);
    		}
    	}
    	for (int i=1;i<=ll;i++)
    	  for (int j=1;j<=rl;j++)
    	    if (jud(a[lt[i]],a[rt[j]]))
    	      insert(lt[i],rt[j],inf);
    	dinic();
    	printf("%d
    ",tot-ans);
    }
    

      

    ——by zhber,转载请注明来源
  • 相关阅读:
    ffmpeg处理视频与声音
    吸引力
    bzoj 2752: [HAOI2012]高速公路(road)
    bzoj 3653 [湖南集训]谈笑风生
    bzoj 3143: [Hnoi2013]游走
    16,docker入门
    15.9,python操作redis集群
    15.8,redis-cluster配置
    15.7,哨兵集群
    15.6,redis主从同步
  • 原文地址:https://www.cnblogs.com/zhber/p/4035931.html
Copyright © 2011-2022 走看看