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\n",fw/2,-ct/2);
    return 0;
}

 

posted @ 2016-10-24 10:50  ihopenot  阅读(191)  评论(0编辑  收藏  举报