ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P4134 [BJOI2012]连连看

2019-09-15 22:02:09  阅读:231  来源: 互联网

标签:分数 memset 连连看 int BJOI2012 题目 P4134 define


题目描述

凡是考智商的题里面总会有这么一种消除游戏。不过现在面对的这关连连看可不是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;
}

 

标签:分数,memset,连连看,int,BJOI2012,题目,P4134,define
来源: https://www.cnblogs.com/wangyiding2003/p/11524495.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有