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

    [BeiJing wc2012]连连看

    题目连接:

    http://www.lydsy.com/JudgeOnline/problem.php?id=2661

    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

    1<=a,b<=1000

    题意

    题解:

    费用流的水题,如果i,j之间能够删去的话,就S-i-j-T,费用为(-i-j),流量为1

    你会发现是个二分图的模型。

    如果流经过了i到达j的话,那么j也会显然选择i的,所以最后答案要除以2.

    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    struct ZKW_MinCostMaxFlow{
    
        const static int maxn = 1e5 + 50;
        const static int maxE = 1e5 + 50;
        const static int INF = 0x3f3f3f3f;
    
        struct Edge{
            int to,next,cap,flow,cost;
            Edge(int _to=0,int _next=0,int _cap=0,int _flow=0,int _cost=0):
                to(_to),next(_next),cap(_cap),flow(_flow),cost(_cost){}
        }edge[maxE * 2];
    
        int head[maxn],tot;
        int cur[maxn];
        int dis[maxn];
        bool vis[maxn];
        int ss,tt,N;
        int min_cost,max_flow;
        void init(int N){
            tot=0;
            for( int i = 0 ; i < N ; ++ i ) head[i] = -1;
        }
        int addedge(int u,int v,int cap,int cost){
            edge[tot]=Edge(v,head[u],cap,0,cost);
            int rs = tot;
            head[u]=tot++;
            edge[tot]=Edge(u,head[v],0,0,-cost);
            head[v]=tot++;
            return rs;
        }
        int aug(int u,int flow){
            if(u==tt) return flow;
            vis[u]=true;
            for(int i=cur[u];i!=-1;i=edge[i].next){
                int v=edge[i].to;
                if( edge[i].cap>edge[i].flow && !vis[v] && dis[u]==dis[v]+edge[i].cost ){
                    int tmp=aug(v,min(flow,edge[i].cap-edge[i].flow));
                    edge[i].flow+=tmp;
                    edge[i^1].flow-=tmp;
                    cur[u]=i;
                    if(tmp) return tmp;
                }
            }
            return 0;
        }
        bool modify_label(){
            int d=INF;
            for(int u=0;u<N;u++){
                if(vis[u])
                for(int i=head[u];i!=-1;i=edge[i].next){
                    int v=edge[i].to;
                    if(edge[i].cap>edge[i].flow && !vis[v])
                        d=min(d,dis[v]+edge[i].cost-dis[u]);
                }
            }
            if(d==INF) return false;
                for(int i=0;i<N;i++)
                if(vis[i]){
                    vis[i]=false;
                    dis[i]+=d;
                }
            return true;
        }
        pair < int , int > mincostmaxflow(int start,int ed,int n ){
            ss=start,tt=ed,N=n;
            min_cost=max_flow=0;
            for(int i=0;i<n;i++) dis[i]=0;
            while(1){
                for(int i=0;i<n;i++) cur[i]=head[i];
                while(1){
                    for(int i=0;i<n;i++) vis[i]=false;
                    int tmp=aug(ss,INF);
                    if(tmp==0) break;
                    max_flow+=tmp;
                    min_cost+=tmp*dis[ss];
                }
                if(!modify_label()) break;
            }
            return make_pair( max_flow , min_cost );
        }
    }solver;
    int gcd(int a,int b){
        return b==0?a:gcd(b,a%b);
    }
    bool check(int a,int b){
        if(a==b)return false;
        if(a<b)swap(a,b);
        int t = sqrt(a*a-b*b);
        if(t*t!=a*a-b*b)return false;
        if(gcd(b,t)!=1)return false;
        return true;
    }
    int main(){
        int a,b;
        scanf("%d%d",&a,&b);
        solver.init(b*2+5);
        for(int i=a;i<=b;i++){
            for(int j=a;j<=b;j++){
                if(check(i,j)){
                    solver.addedge(i,j+b,1,-i-j);
                }
            }
            solver.addedge(b*2+1,i,1,0);
            solver.addedge(i+b,b*2+2,1,0);
        }
        pair<int,int>ans=solver.mincostmaxflow(b*2+1,b*2+2,b*2+5);
        printf("%d %d
    ",ans.first/2,-ans.second/2);
    }
  • 相关阅读:
    python基础1.0
    时间紧的跟狗一样,不动摇坚持下去!
    STM32(十三)- SDIO_SD读写测试
    STM32(十二)- TIM基本定时器和高级定时器
    STM32(十一)- 串行FLASH文件系统FatFs
    STM32(十)- SPI
    STM32(九)- I2C
    STM32(八)- DMA和常用存储器
    STM32(七)- UART
    STM32(六)- SysTick
  • 原文地址:https://www.cnblogs.com/qscqesze/p/6628550.html
Copyright © 2011-2022 走看看