zoukankan      html  css  js  c++  java
  • P4134 [BJOI2012]连连看

    题目描述

    凡是考智商的题里面总会有这么一种消除游戏。不过现在面对的这关连连看可不是QQ游戏里那种考眼力的游戏。我们的规则是,给出一个闭区间[a,b]中的全部整数,如果其中某两个数x,y(设x>y)的平方差x^2-y^2是一个完全平方数z^2,并且y与z互质,那么就可以将x和y连起来并且将它们一起消除,同时得到x+y点分数。那么过关的要求就是,消除的数对尽可能多的前提下,得到足够的分数。快动手动笔算一算吧。

    输入格式

    只有一行,两个整数,分别表示a,b。

    输出格式

    两个数,可以消去的对数,及在此基础上能得到的最大分数。

    输入输出样例

    输入 #1
    1 15
    输出 #1
    2 34

    说明/提示

    对于30%的数据,1<=a,b<=100

    对于100%的数据,1<=a,b<=1000

    思路

    从题目中可看出这题为拆点并跑最大流最大费用。对于每个符合题目条件的(i,j),我们拆为i,i+b,j,j+b。并将i与j+b,i+b与j相连,建边,这样虽然可以省去自己与自己建边,但需要将结果除去2。

    代码

    #include<bits/stdc++.h>
    #define N 10700
    #define M 107000
    #define inf 1<<29
    using namespace std;
    struct node{
        int y,z,p,next;
    }e[M*2];
    int tot=1,head[N],maxflow=0,ans=0,s,t;
    void add(int x,int y,int z,int p){
        e[++tot].y=y;e[tot].z=z;e[tot].p=p;
        e[tot].next=head[x];head[x]=tot;
    }
    int incf[N],v[N],pre[N],d[N];
    bool spfa(){
        queue<int> q;
        memset(d,0xcf,sizeof(d));
        memset(v,0,sizeof(v));
        q.push(s);d[s]=0;v[s]=1;
        incf[s]=inf;
        while(q.size()){
            int x=q.front();v[x]=0;q.pop();
            for(int i=head[x];i;i=e[i].next){
                int y=e[i].y,z=e[i].z;
                if(!z) continue;
                if(d[y]<d[x]+e[i].p){
                    d[y]=d[x]+e[i].p;
                    incf[y]=min(incf[x],z);
                    pre[y]=i;
                    if(!v[y]) v[y]=1,q.push(y);
                }
            }
        }
        if(d[t]==0xcfcfcfcf) return false;
        return true;
    }
    void update(){
        int x=t;
        while(x!=s){
            int i=pre[x];
            e[i].z-=incf[t];
            e[i^1].z+=incf[t];
            x=e[i^1].y; 
        }
        maxflow+=incf[t];
        ans+=d[t]*incf[t];
    }
    int n=1000;
    int gcd(int a,int b){
        return b==0?a:gcd(b,a%b);
    }
    int f(int x,int y){
        int k=x*x-y*y;
        int g=sqrt(k);
        if(g*g==k&&gcd(y,g)==1) return 1;
        else return 0;
    }
    int main()
    {
        int a,b;
        cin>>a>>b;
        s=0;t=b+1;n=b;
        for(int i=a;i<=b;i++)
            add(s,i,1,0),add(i,s,0,0);
        for(int i=a+b;i<=b+b;i++)
            add(i,t,1,0),add(t,i,0,0);
        for(int i=a;i<=b;i++){
            for(int j=a;j<i;j++){
                if(f(i,j)){
                    add(j,i+b,1,i+j);add(i+b,j,0,-i-j);
                    add(i,j+b,1,i+j),add(j+b,i,0,-i-j);
                }
            }
        }
        while(spfa()) 
            update();
        cout<<maxflow/2<<" "<<ans/2<<endl;
        return 0;
    }
  • 相关阅读:
    curd_4
    curd_2
    Python Regex库的使用
    Python Assert 确认条件为真的工具
    Python Regex库的使用(2)
    Python lambda的用法
    Python 列表综合
    with ss(date,date2) (select * from sysdummy1) select * from ss
    延迟执行函数
    ObjectiveC 的基本数据类型、数字、字符串和集合等介绍
  • 原文地址:https://www.cnblogs.com/wangyiding2003/p/11524495.html
Copyright © 2011-2022 走看看