zoukankan      html  css  js  c++  java
  • Bzoj2661--Wc2012连连看

    暴力预处理出可行点对,拆点后跑最小费用最大流,费用取负

    连边要对连,就是x->y和y->x都要连,最后除2才是答案

    因为这里每个数只能匹配一次,对连的话同一个点两边都会采用同样的连法所以可以避免多次匹配

    代码:

    #include<bits/stdc++.h>
    #define INF 1000000000
    using namespace std;
    inline double _fabs(double a) {return a>0?a:-a;}
    
    inline int read() {
        int ret=0,f=1;char c=getchar();
        while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
        while(c<='9'&&c>='0') {ret=ret*10+c-'0';c=getchar();}
        return ret*f;
    }
    inline int gcd(int a,int b) {
        int t;
        while(b) {t=a;a=b;b=t%b;}
        return a;
    }
    
    #define fix 1000
    #define MAXN 2005
    #define MAXM 10005
    
    const int S=2002,T=2003;
    int L,R;
    
    int head[MAXN],cnt=1;
    struct Edge{
        int to,flow,cap,next,cost,from;
    }e[MAXM];
    inline void insert(int a,int b,int f,int c) {
        e[++cnt].next=head[a];head[a]=cnt;e[cnt].to=b;e[cnt].flow=f;e[cnt].cap=0;e[cnt].cost=c;e[cnt].from=a;
        e[++cnt].next=head[b];head[b]=cnt;e[cnt].to=a;e[cnt].flow=0;e[cnt].cap=0;e[cnt].cost=-c;e[cnt].from=b;
    }
    
    queue<int> q;int z[MAXN],bk[MAXN];bool f[MAXN];
    int updata(){
        int a=INF;
        for(int i=bk[T];i;i=bk[e[i].from]) {
            a=min(a,e[i].flow-e[i].cap);
        }
        for(int i=bk[T];i;i=bk[e[i].from]) {
            e[i].cap+=a;e[i^1].cap-=a;
        }
        return a;
    }
    int fw,ct;
    int spfa() {
        int k;memset(z,0x3f3f,sizeof(z));
        q.push(S);z[S]=0;f[S]=1;
        while(!q.empty()) {
            k=q.front();q.pop();
            for(int i=head[k];i;i=e[i].next) {
                if(z[e[i].to]>z[k]+e[i].cost&&e[i].flow>e[i].cap) {
                    bk[e[i].to]=i;z[e[i].to]=e[i].cost+z[k];
                    if(!f[e[i].to]){q.push(e[i].to);f[e[i].to]=1;}
                }
            }
            f[k]=0;
        }
        if(z[T]<0x3f3f3f3f) k=updata();
        else k=0;ct+=k*z[T];
        return k;
    }
    void MSMF() {
        int f;
        while(f=spfa()) fw+=f;
    }
    
    int main() {
        L=read();R=read();
        for(int w,t,i=L;i<R;i++) for(int j=i+1;j<=R;j++) {
            w=j*j-i*i;t=sqrt(w);
            if(t*t==w&&gcd(i,t)==1) {
                insert(i,j+fix,1,-i-j);
                insert(j,i+fix,1,-i-j);
            }
        }
        for(int i=L;i<=R;i++) {insert(S,i,1,0);insert(i+fix,T,1,0);}
        MSMF();
        printf("%d %d
    ",fw/2,-ct/2);
        return 0;
    }
  • 相关阅读:
    oracle 之监听保护
    游戏升级之路
    《C++游戏开发》十六 游戏中的寻路算法(二):迷宫&A*算法基础
    【JavaScript】实现复选框的全选、全部不选、反选
    虎嗅: 小米盒子vs乐视盒子
    即将成为传奇的微软
    DB-Oracle-DatabaseLinks:百科
    人物-思想家-默罕默德:百科
    ADO.NET:目录
    ADO.NET:百科
  • 原文地址:https://www.cnblogs.com/ihopenot/p/5992125.html
Copyright © 2011-2022 走看看