zoukankan      html  css  js  c++  java
  • 【BZOJ】【3275】Numbers

    网络流/最小割


      Orz了Jiry_2神犇,蒟蒻网络流建模什么的完全不会啊T_T

      按奇偶性来分组实在太巧妙了……然后相关的点之间连边表示只能选其一,来求最小割……

      1 /**************************************************************
      2     Problem: 3275
      3     User: Tunix
      4     Language: C++
      5     Result: Accepted
      6     Time:1252 ms
      7     Memory:1708 kb
      8 ****************************************************************/
      9  
     10 //BZOJ 3275
     11 #include<cmath>
     12 #include<vector>
     13 #include<cstdio>
     14 #include<cstring>
     15 #include<cstdlib>
     16 #include<iostream>
     17 #include<algorithm>
     18 #define rep(i,n) for(int i=0;i<n;++i)
     19 #define F(i,j,n) for(int i=j;i<=n;++i)
     20 #define D(i,j,n) for(int i=j;i>=n;--i)
     21 #define pb push_back
     22 using namespace std;
     23 inline int getint(){
     24     int v=0,sign=1; char ch=getchar();
     25     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
     26     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
     27     return v*sign;
     28 }
     29 const int N=3100,M=30010,INF=~0u>>2;
     30 typedef long long LL;
     31 /******************tamplate*********************/
     32 int n,m,a[3010],tot,ans;
     33 struct edge{
     34     int to,v;
     35 };
     36 int gcd(int a,int b){if (!b) return a;else return gcd(b,a%b);}
     37 bool judge(int a,int b){
     38     int s=a*a+b*b;
     39     int q=int(sqrt(s));
     40     if (q*q!=s) return 0;
     41     if (gcd(a,b)!=1) return 0;
     42     return 1;
     43 }
     44 struct Net{
     45     edge E[M];
     46     int head[N],next[M],cnt;
     47     bool vis[110][110];
     48     void ins(int x,int y,int v){
     49         E[++cnt]=(edge){y,v};
     50         next[cnt]=head[x]; head[x]=cnt;
     51     }
     52     void add(int x,int y,int v){
     53         ins(x,y,v); ins(y,x,0);
     54     }
     55     int s,t,cur[N],d[N],Q[N];
     56     void init(){
     57         n=getint();cnt=1;
     58         tot=ans=0;
     59         s=0; t=n+1;
     60         F(i,1,n){
     61             a[i]=getint();tot+=a[i];
     62             if (a[i]&1) add(s,i,a[i]);
     63             else add(i,t,a[i]);
     64         }
     65         F(i,1,n) if (a[i]&1)
     66             F(j,1,n) if ((a[j]&1)==0)
     67                 if (judge(a[i],a[j])) add(i,j,INF);
     68     }
     69     bool mklevel(){
     70         memset(d,-1,sizeof d);
     71         d[s]=0;
     72         int l=0,r=-1;
     73         Q[++r]=s;
     74         while(l<=r){
     75             int x=Q[l++];
     76             for(int i=head[x];i;i=next[i])
     77                 if (d[E[i].to]==-1 && E[i].v){
     78                     d[E[i].to]=d[x]+1;
     79                     Q[++r]=E[i].to;
     80                 }
     81         }
     82         return d[t]!=-1;
     83     }
     84     int dfs(int x,int a){
     85         if (x==t) return a;
     86         int flow=0;
     87         for(int &i=cur[x];i && flow<a;i=next[i])
     88             if (E[i].v && d[E[i].to]==d[x]+1){
     89                 int f=dfs(E[i].to,min(a-flow,E[i].v));
     90                 E[i].v-=f;
     91                 E[i^1].v+=f;
     92                 flow+=f;
     93             }
     94         if (!flow) d[x]=-1;
     95         return flow;
     96     }
     97     void Dinic(){
     98         while(mklevel()){
     99             F(i,s,t) cur[i]=head[i];
    100             ans+=dfs(s,INF);
    101         }
    102     }
    103 }G1;
    104 int main(){
    105 #ifndef ONLINE_JUDGE
    106     freopen("3275.in","r",stdin);
    107     freopen("3275.out","w",stdout);
    108 #endif
    109     G1.init(); G1.Dinic();
    110     printf("%d
    ",tot-ans);
    111     return 0;
    112 }
    View Code

    3275: Number

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 495  Solved: 217
    [Submit][Status][Discuss]

    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。

    Source

    [Submit][Status][Discuss]
  • 相关阅读:
    微服务实战系列(七)-网关springcloud gateway
    微服务实战系列(六)-网关springcloud zuul
    微服务实战系列(五)-注册中心Eureka与nacos区别
    微服务实战系列(四)-注册中心springcloud alibaba nacos
    中国唯一入选 Forrester 领导者象限,阿里云 Serverless 全球领先
    面对不可避免的故障,我们造了一个“上帝视角”的控制台
    实习就参与“服务过亿用户的项目”,是什么体验?
    Go Mysql Driver 集成 Seata-Golang 解决分布式事务问题
    云原生时代下,容器安全的“四个挑战”和“两个关键”
    OpenKruise v0.8.0 核心能力解读:管理 Sidecar 容器的利器
  • 原文地址:https://www.cnblogs.com/Tunix/p/4338824.html
Copyright © 2011-2022 走看看