zoukankan      html  css  js  c++  java
  • bzoj 3158 千钧一发——网络流

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3158

    发现偶数之间一定满足第二个条件;奇数之间一定满足第一个条件 ( ( (2m+1)^{2}+(2n+1)^{2}=4m^{2}+4m+1+4n^{2}+4n+1 ),这是个偶数,所以 T2 的 T 一定是偶数;偶数的平方一定是4的倍数,不能有那个 +2  )。

    所以如果把不合法的连起来,就是一个二分图。可以用最小割做,不合法之间的连边是 INF 这样。

    注意判断第一个条件的时候不用在 12~1414222 之间二分(虽然时间和 gcd 时间一样),只需要求一下根号看看是不是整数就行了。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define ll long long
    using namespace std;
    const int N=1005,M=502005,K=1e6+5,Lm=141425,INF=1e9+5;
    int n,a[N],b[N],hd[N],xnt=1,cur[N],nxt[M],to[M],cap[M];
    int dfn[N],q[N],he,tl;  ll s[N];
    int Mx(int a,int b){return a>b?a:b;}
    int Mn(int a,int b){return a<b?a:b;}
    int gcd(int a,int b){return b?gcd(b,a%b):a;}
    ll Sqr(int x){return (ll)x*x;}
    void add(int x,int y,int z)
    {
        to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;cap[xnt]=z;
        to[++xnt]=x;nxt[xnt]=hd[y];hd[y]=xnt;cap[xnt]=0;
    }
    bool chk(ll x)
    {
        ll k=sqrt(x);
        return k*k!=x;//!=
    }
    bool bfs()
    {
        memset(dfn,0,sizeof dfn);dfn[0]=1;
        q[he=tl=1]=0;
        while(he<=tl)
        {
            int k=q[he++];
            for(int i=hd[k],v;i;i=nxt[i])
                if(cap[i]&&!dfn[v=to[i]])
                    dfn[v]=dfn[k]+1,q[++tl]=v;
        }
        return dfn[n+1];
    }
    int dinic(int cr,int flow)
    {
        if(cr==n+1)return flow;
        int use=0;
        for(int& i=cur[cr],v;i;i=nxt[i])
            if(cap[i]&&dfn[v=to[i]]==dfn[cr]+1)
            {
                int tmp=dinic(v,Mn(flow-use,cap[i]));
                if(!tmp)dfn[v]=0;
                use+=tmp;cap[i]-=tmp;cap[i^1]+=tmp;
                if(use==flow)return use;
            }
        return use;
    }
    int main()
    {
        scanf("%d",&n);int ans=0;
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),s[i]=Sqr(a[i]);
        for(int i=1;i<=n;i++)scanf("%d",&b[i]),ans+=b[i];
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
            {
                if(gcd(a[i],a[j])>1||chk(s[i]+s[j]))continue;
                a[i]&1?add(i,j,INF):add(j,i,INF);
            }
        for(int i=1;i<=n;i++)
            if(a[i]&1)add(0,i,b[i]); else add(i,n+1,b[i]);
        while(bfs())memcpy(cur,hd,sizeof hd),ans-=dinic(0,INF);
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    访问虚拟机
    w3school JavaScript 简介
    蘑菇街2016研发工程师在线编程题
    乐视2017暑期实习生笔试题(二)
    今日头条2017后端工程师实习生笔试题
    c# 读取 excel文件内容,写入txt文档
    处理字符串
    XML获取节点信息值
    SVN仓库目录结构
    sql 知识点
  • 原文地址:https://www.cnblogs.com/Narh/p/10161724.html
Copyright © 2011-2022 走看看