zoukankan      html  css  js  c++  java
  • [bzoj3275]Number

    暴力枚举两个数字并判定,如果不能同时选就连边,然后即求最大带权独立集。

    普通图的最大带权独立集无法快速求出,但发现两个奇数一定无法使得1式成立(考虑模8,奇数平方模81,偶数平方模804),两个偶数一定无法使2式成立,因此奇数和偶数内部没有边,即形成了一张二分图。

    首先假设所有数都可以选,考虑最少要删掉多少:1.将左半部分的点与源点连价值的边;2.将右半部分的点向汇点连价值的边;3.两者之间不能同时选的连一条inf的边。然后跑最小割,这样任意一条inf边的两端必须有一条边被删掉(不选),所以答案就是最大流了。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 3005
     4 #define inf 0x3f3f3f3f
     5 struct ji{
     6     int nex,to,len;
     7 }edge[N*N];
     8 queue<int>q;
     9 int E,n,ans,a[N],head[N],work[N],d[N];
    10 void add(int x,int y,int z){
    11     edge[E].nex=head[x];
    12     edge[E].to=y;
    13     edge[E].len=z;
    14     head[x]=E++;
    15     if (E&1)add(y,x,0);
    16 }
    17 int gcd(int x,int y){
    18     if (!y)return x;
    19     return gcd(y,x%y);
    20 }
    21 bool bfs(){
    22     memset(d,-1,sizeof(d));
    23     q.push(0);
    24     d[0]=0;
    25     while (!q.empty()){
    26         int k=q.front();
    27         q.pop();
    28         for(int i=head[k];i!=-1;i=edge[i].nex)
    29             if ((edge[i].len)&&(d[edge[i].to]<0)){
    30                 d[edge[i].to]=d[k]+1;
    31                 q.push(edge[i].to);
    32             }
    33     }
    34     return d[n+1]>=0;
    35 }
    36 int dfs(int k,int s){
    37     if (k>n)return s;
    38     int p;
    39     for(int i=head[k];i!=-1;i=edge[i].nex)
    40         if ((edge[i].len)&&(d[edge[i].to]==d[k]+1)){
    41             p=dfs(edge[i].to,min(s,edge[i].len));
    42             if (p){
    43                 edge[i].len-=p;
    44                 edge[i^1].len+=p;
    45                 return p;
    46             }
    47         }
    48     return 0;
    49 }
    50 int dinic(){
    51     int k,ans=0;
    52     while (bfs()){
    53         memcpy(work,head,sizeof(head));
    54         while (k=dfs(0,inf))ans+=k;
    55     }
    56     return ans;
    57 }
    58 int main(){
    59     scanf("%d",&n);
    60     memset(head,-1,sizeof(head));
    61     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    62     for(int i=1;i<=n;i++)ans+=a[i];
    63     for(int i=1;i<=n;i++)
    64         if (a[i]&1)add(0,i,a[i]);
    65         else add(i,n+1,a[i]);
    66     for(int i=1;i<=n;i++)
    67         if (a[i]&1)
    68             for(int j=1;j<=n;j++){
    69                 if (gcd(a[i],a[j])>1)continue;
    70                 int c=a[i]*a[i]+a[j]*a[j];
    71                 if (c==(int)sqrt(c)*(int)sqrt(c))add(i,j,inf);
    72             }
    73     printf("%d",ans-dinic());
    74 }
    View Code
  • 相关阅读:
    gitlab 本地 定时备份
    centos 7 部署 汉化版 gitlab
    ELK开机启动 service文件内容
    通过 kms 激活 office 2016
    让 kibana 后台启动的方案
    centos7 yum 安装 redis
    域账户登录时提示“你的账户配置不允许使用这台电脑。请试一下其他电脑” 解决方案
    gitlab 接入 openldap、AD
    VS访问不到TFS、VS连接TFS报TF30063
    php--纯静态和伪静态的区别与关系
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11249786.html
Copyright © 2011-2022 走看看