2661: [BeiJing wc2012]连连看

来源:互联网 发布:淘宝手机端连接 编辑:程序博客网 时间:2024/05/16 09:06

2661: [BeiJing wc2012]连连看

Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 1288 Solved: 536
[Submit][Status][Discuss]
Description

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

Input

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

Output

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

Sample Input

1 15

Sample Output

2 34

HINT

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

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

这题感觉挺简单的吧。。
第一眼下去,smg,一般图最大权匹配?带花树开花?
算了吧,不存在的
考虑费用流
算了,没什么好说的,看代码吧。。
话说我很早以前就想遇到一题这样构图的题了,终于给我找到了
没错,这个图就是高度对称的,这一点和2-sat有一点像
于是就可以乱做了

但是有一点我很奇怪
就是要是我吧边权弄为正的,跑最大费用流,会GG
但是,我以前都是这样用的啊QAQ,难道我一直都错了?
于是我改为相反数,跑最小费用就AC了

#include<cstdio>#include<queue>#include<algorithm>#include<cstring>#include<iostream>#include<cstring>#include<cmath>using namespace std;const int N=1005*2;const int MAX=1<<30;int a,b;int gcd (int x,int y){    if (y%x==0) return x;    return gcd(y%x,x);}bool check(int y,int x)  {      int tmp=x*x-y*y,z=(int)sqrt(tmp);      if (z*z!=tmp) return false;      if (y<z) swap(y,z);      while (z){tmp=y%z;y=z;z=tmp;}      return (y==1);}  struct qq{    int x,y,z,z1,last;//流量    费用 }s[2000000];int num,last[N];int st,ed;void init (int x,int y,int z,int z1){    num++;    s[num].x=x;s[num].y=y;s[num].z=z;s[num].z1=z1;    s[num].last=last[x];    last[x]=num;    swap(x,y);z=0;z1=-z1;    num++;    s[num].x=x;s[num].y=y;s[num].z=z;s[num].z1=z1;    s[num].last=last[x];    last[x]=num;}int from[N];int f[N];bool in[N];bool SPFA (){    memset(in,false,sizeof(in));    memset(from,-1,sizeof(from));    memset(f,127,sizeof(f));    queue<int> q;    q.push(st);    f[st]=0;in[st]=true;    while (!q.empty())    {        int x=q.front();q.pop();        for (int u=last[x];u!=-1;u=s[u].last)        {            int y=s[u].y;            if (s[u].z>0&&f[y]>f[x]+s[u].z1)            {                f[y]=f[x]+s[u].z1;                from[y]=u;                if (in[y]==false)                {                    in[y]=true;                    q.push(y);                }            }        }        in[x]=false;    }    return from[ed]!=-1;}int mymin (int x,int y){    return x<y?x:y;}int ans=0;void lalal (){    int x=from[ed],t=MAX;    while (x!=-1)    {        t=mymin(t,s[x].z);        x=from[s[x].x];    }    x=from[ed];    while (x!=-1)    {        ans=ans+t*s[x].z1;        s[x].z-=t;        s[x^1].z+=t;        x=from[s[x].x];    }    return ;}int main(){    num=1;memset(last,-1,sizeof(last));    scanf("%d%d",&a,&b);    st=2001;ed=st+1;    for (int u=a;u<=b;u++)        for (int i=u+1;i<=b;i++)            if (check(u,i))            {                init(u,i+1000,1,-u-i),init(i,u+1000,1,-u-i);            }    for (int u=a;u<=b;u++)   init(st,u,1,0),init(u+1000,ed,1,0);    while (SPFA()==true) lalal();    int shen=0;    for (int u=last[st];u!=-1;u=s[u].last)    {        if (u%2==0)//他是自己连出去的             if (s[u].z==0)                shen++;    }    printf("%d %d\n",shen/2,-ans/2);    return 0;}
原创粉丝点击