BZOJ 2661 连连看(费用流)

题目链接: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

时间: 2024-10-10 17:32:45

BZOJ 2661 连连看(费用流)的相关文章

BZOJ 1070 修车(费用流)

如果能想到费用流,这道题就是显然了. 要求所有人的等待平均时间最小,也就是所有人的总等待时间最小. 每辆车只需要修一次,所以s连每辆车容量为1,费用为0的边. 现在需要把每个人拆成n个点,把车和每个人的第k个点连一条容量为1,费用为cost[i][j]*k的边. 最后把每个人拆完后的点向汇点连一条容量为1,费用为0的边. #include<iostream> #include<cstdio> #include<cstring> #define inf 0x7ffffff

BZOJ 3130: [Sdoi2013]费用流 网络流+二分

3130: [Sdoi2013]费用流 Time Limit: 10 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 1230  Solved: 598[Submit][Status][Discuss] Description Alice和Bob在图论课程上学习了最大流和最小费用最大流的相关知识.     最大流问题:给定一张有向图表示运输网络,一个源点S和一个汇点T,每条边都有最大流量.一个合法的网络流方案必须满足:(1)每条边的实际流量都

BZOJ 1283 序列 费用流

题目大意:给定一个长度为n的序列,要求选一些数,使得任意一个长度为m个区间中最多选k个数,求最大的和 费用流直接跑就是了 把这个序列用流量为k费用为0的边连成一条直线 然后第i个点向第i+m个点连一条费用为a[i]流量为1的边 跑最大费用最大流即可 卡单纯型差评.... #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 1010 #d

bzoj 3130 [Sdoi2013]费用流(二分,最大流)

Description Alice和Bob在图论课程上学习了最大流和最小费用最大流的相关知识.    最大流问题:给定一张有向图表示运输网络,一个源点S和一个汇点T,每条边都有最大流量.一个合法的网络流方案必须满足:(1)每条边的实际流量都不超过其最大流量且非负:(2)除了源点S和汇点T之外,对于其余所有点,都满足该点总流入流量等于该点总流出流量:而S点的净流出流量等于T点的净流入流量,这个值也即该网络流方案的总运输量.最大流问题就是对于给定的运输网络,求总运输量最大的网络流方案.   上图表示

【SDOI 2013】【BZOJ 3130】费用流

这题的第一问是一个裸最大流,不多说了,关键在于第二问.首先有一个结论,Bob一定把费用加在一条边上,于是我们就可以二分每条边的流量,验证是否能得到最大流即可 code: #include<iostream> #include<cstdio> #include<cstring> #define inf 0x7fffffff using namespace std; int n,m,p,e,ei; int point[101],next[2001]; int cur[101

BZOJ 3130 [Sdoi2013]费用流 ——网络流

[题目分析] 很容易想到,可以把P放在流量最大的边上的时候最优. 所以二分网络流,判断什么时候可以达到最大流. 流量不一定是整数,所以需要实数二分,整数是会WA的. [代码] #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> //#include <map> #include <set> #include <queue> #in

BZOJ 2661 连连看

http://www.lydsy.com/JudgeOnline/problem.php?id=2661 思路:预处理出每个数字,然后若有x^2=y^2+z^2且z与y互质, s->x 1 ,0 x+n-> t 1 , 0 x->y+n -> 1 , inf-x-y y->x+n-> 1 ,inf-x-y 1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #inc

bzoj 3130: [Sdoi2013]费用流

1 #include<cstdio> 2 #include<iostream> 3 #define M 10000 4 #define inf 0x7fffffff 5 #include<cstring> 6 #define eps 1e-5 7 using namespace std; 8 struct data 9 { 10 int x,y; 11 double z; 12 }a[M]; 13 int d[M],q[M],S,T,cnt=1,n,m,head[M],

BZOJ 1283 序列 费用流 网络流 线性规划

https://darkbzoj.cf/problem/1283 给出一个长度为N的正整数序列Ci,求一个子序列,使得原序列中任意长度为M的子串中被选出的元素不超过K(K,M<=100) 个,并且选出的元素之和最大. http://www.cnblogs.com/137shoebills/p/8871648.html ↑和这道题一样 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #i