码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 2661 连连看(费用流)

时间:2014-06-23 00:49:29      阅读:215      评论:0      收藏:0      [点我收藏+]

标签:style   class   blog   http   tar   ext   

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2661

题意:给出一个区间[a,b]中的全部整数,如果其中某两个数x,y(设x>y)的平方差x^2-y^2是一个完全平方数z^2,并且y与z互质,那么就可以将x和y一起消除,同时得到x+y点分数。要求就是,消除的数对尽可能多的前提下,得到的分数尽量多。

思路:首先暴力出所有合法的数对(x,y)。然后将每个用到的数字拆成两个点,每个数对连一条边。最后的答案除以2即可。

 

struct node
{
    int u,v,next,cost,cap;
};




node edges[N*100];
int head[N],e;




void add(int u,int v,int cap,int cost)
{
    edges[e].u=u;
    edges[e].v=v;
    edges[e].cap=cap;
    edges[e].cost=cost;
    edges[e].next=head[u];
    head[u]=e++;
}




void Add(int u,int v,int cap,int cost)
{
    add(u,v,cap,cost);
    add(v,u,0,-cost);
}




int pre[N],F[N],C[N],visit[N];




int SPFA(int s,int t,int n)
{
    int i;
    for(i=0;i<=n;i++) F[i]=0,C[i]=INF*10000,visit[i]=0;
    queue<int> Q;
    Q.push(s); F[s]=INF; C[s]=0;
    int u,v,cost,cap;
    while(!Q.empty())
    {
        u=Q.front();
        Q.pop();
        
        visit[u]=0;
        for(i=head[u];i!=-1;i=edges[i].next)
        {
            if(edges[i].cap>0)
            {
                v=edges[i].v;
                cost=edges[i].cost;
                cap=edges[i].cap;
                if(C[v]>C[u]+cost)
                {
                    C[v]=C[u]+cost;
                    F[v]=min(F[u],cap);
                    pre[v]=i;
                    if(!visit[v]) visit[v]=1,Q.push(v);
                }
            }
        }
    }
    return F[t];
}




void MCMF(int s,int t,int n)
{
    int i,x,temp,M=0;
    int ans=0;
    while(temp=SPFA(s,t,n))
    {
        M+=temp;
        for(i=t;i!=s;i=edges[pre[i]].u)
        {
            x=pre[i];
            ans+=edges[x].cost*temp;
            edges[x].cap-=temp;
            edges[x^1].cap+=temp;
        }
    }
    PR(M>>1,(M*INF-ans)>>1);
}


int n,m,s,t,cnt;


int Gcd(int x,int y)
{
    if(y==0) return x;
    return Gcd(y,x%y);
}


int c[N*N],b[N],L[400],R[400];


int main()
{
    RD(n,m); 
    if(n>m) swap(n,m);
    int i,j,k;
    for(i=1;i<=1000;i++) c[i*i]=i;
    for(i=n;i<=m;i++) for(j=i+1;j<=m;j++)
    {
        k=j*j-i*i;
        if(c[k]&&Gcd(i,c[k])==1)
        {
            b[i]=b[j]=1;
            cnt++;
            L[cnt]=i; R[cnt]=j;
        }
    }
    int x=0;
    for(i=n;i<=m;i++) if(b[i]) b[i]=++x;
    s=0; t=x+x+1;
    clr(head,-1);
    for(i=n;i<=m;i++) if(b[i]) Add(s,b[i],1,0),Add(b[i]+x,t,1,0);
    FOR1(i,cnt) 
    {
        Add(b[L[i]],x+b[R[i]],1,INF-L[i]-R[i]);
        Add(b[R[i]],x+b[L[i]],1,INF-L[i]-R[i]);
    }
    MCMF(s,t,t+1);
}

 

 

 

BZOJ 2661 连连看(费用流),布布扣,bubuko.com

BZOJ 2661 连连看(费用流)

标签:style   class   blog   http   tar   ext   

原文地址:http://www.cnblogs.com/jianglangcaijin/p/3799791.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!