zoukankan      html  css  js  c++  java
  • [BZOJ2661][BeiJing wc2012]连连看 费用流

    2661: [BeiJing wc2012]连连看

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 1349  Solved: 577
    [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

    Source

    拆点直接连边。跑最大费用最大流,答案/2。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cmath>
     5 #include<cstdio>
     6 #include<algorithm>
     7 using namespace std;
     8 struct data {
     9     int cost,w,to,next;
    10 }e[100000];
    11 int head[10000],cnt;
    12 int S,T; 
    13 void add(int u,int v,int w,int c) {
    14     e[cnt].to=v;e[cnt].next=head[u];e[cnt].w=w;e[cnt].cost=c;head[u]=cnt++;
    15     e[cnt].to=u;e[cnt].next=head[v];e[cnt].w=0;e[cnt].cost=-c;head[v]=cnt++;
    16 }
    17 int dis[10000];
    18 bool vis[10000];
    19 int q[10000],used;
    20 bool spfa() {
    21     memset(dis,-37,sizeof(dis));
    22     vis[T]=1;dis[T]=0;
    23     int h=0,t=1;
    24     q[0]=T;
    25     while(h!=t) {
    26         int now=q[h];h++;if(h==10000) h=0;
    27         for(int i=head[now];i>=0;i=e[i].next) {
    28             int to=e[i].to;if(!e[i^1].w) continue;
    29             if(dis[to]<dis[now]-e[i^1].cost) {
    30                 dis[to]=dis[now]-e[i^1].cost;
    31                 if(!vis[to]) {vis[to]=1;q[t++]=to;if(t==10000)t=0;}
    32             }
    33         }
    34         vis[now]=0;
    35     }
    36     used=-dis[S];
    37     return dis[S]!=dis[9999];
    38 }
    39 int ans=0;
    40 int dfs(int x,int a) {
    41     if(x==T) {ans+=used*a;return a;} 
    42     int f=0,flow=0;vis[x]=1;
    43     for(int i=head[x];i>=0;i=e[i].next) {
    44         int to=e[i].to;
    45         if(!vis[to]&&e[i].w>0&&dis[to]==dis[x]+e[i].cost&&(f=dfs(to,min(e[i].w,a)))) {
    46             e[i].w-=f;e[i^1].w+=f;
    47             a-=f;flow+=f;
    48             if(a==0) break;
    49         }
    50     }
    51     return flow;
    52 }
    53 void zkw() {
    54     while(spfa()) {
    55         do {
    56             memset(vis,0,sizeof(vis));
    57         }while(dfs(S,2147483647));
    58         memset(vis,0,sizeof(vis));
    59     }
    60 }
    61 bool check(int x,int y) {
    62     int tmp=x*x-y*y,z=(int)sqrt(tmp);  
    63     if (z*z!=tmp) return false;  
    64     if (y<z) swap(y,z);  
    65     while (z){tmp=y%z;y=z;z=tmp;}  
    66     return (y==1);  
    67 }  
    68 int main() {
    69     memset(head,-1,sizeof(head));
    70     int a,b;
    71     scanf("%d%d",&a,&b);
    72     S=2001;T=2002;  
    73     for(int i=a;i<=b-1;i++) 
    74         for(int j=i+1;j<=b;j++) if (check(j,i)) {  
    75             add(i,j+1000,1,-i-j);
    76             add(j,i+1000,1,-i-j);  
    77         }  
    78     for(int i=a;i<=b;i++) {  
    79         add(S,i,1,0);  
    80         add(i+1000,T,1,0);  
    81     }
    82     zkw();
    83     int tot=0;
    84     for(int i=0;i<cnt;i++) if (e[i].to==T&&!e[i].w) tot++;  
    85     printf("%d %d
    ",tot/2,-ans/2);  
    86 }
    View Code
    O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~
  • 相关阅读:
    工作总结06
    工作总结05
    工作总结04
    站立会议01
    团队项目估算
    团队项目计划会议
    团队需求分析视频
    团队介绍
    团队项目计划会议01
    电梯演讲
  • 原文地址:https://www.cnblogs.com/wls001/p/8416779.html
Copyright © 2011-2022 走看看