zoukankan      html  css  js  c++  java
  • SDOI 2016 数字配对

    题目大意:给定n个数字以及每个数字的个数和权值,将满足条件的数字配对,使得总代价不小于0,且配对最多

    最大费用最大流拆点,对于每个点,连一条由S到该点的边,容量为b,花费为0,再连一条到T的边

    对于每个合法的配对,连一条容量无穷,费用为ci*cj的边

    跑最大费用最大流即可

    #include<bits/stdc++.h>
    using namespace std;
    #define inf (1ll<<50)
    #define ll long long
    struct edge{
        int to,next,flom;
        ll cost,cap;
    }G[200010];
    int tot=1,h[410];
    int S,T,ans;
    ll cost;
    int n;
    int a[210],b[210],c[210];
    void add(int x,int y,ll z,ll c){
        tot++;G[tot].to=y;G[tot].next=h[x];h[x]=tot;G[tot].flom=x;G[tot].cap=z;G[tot].cost=c;
    }
    void ins(int x,int y,ll z,ll c){
        add(x,y,z,c);add(y,x,0,-c);
    }
    ll dis[410];int vis[410],p[410];
    bool check(int x){
        int k=sqrt(x);
        for(int i=2;i<=k;++i)
            if(x%i==0)return 0;
        return 1;
    }
    bool spfa(){
        memset(vis,0,sizeof(vis));
        memset(p,0,sizeof(p));
        for(int i=0;i<=(n<<1|1);++i)dis[i]=-inf;dis[S]=0;
        queue<int>Q;Q.push(S);vis[S]=1;
        while(!Q.empty()){
            int u=Q.front();Q.pop();vis[u]=0;
            for(int i=h[u];i;i=G[i].next){
                int v=G[i].to;
                if(G[i].cap>0&&dis[v]<dis[u]+G[i].cost){
                    dis[v]=dis[u]+G[i].cost;p[v]=i;
                    if(!vis[v])vis[v]=1,Q.push(v);
                }
            }
        }
        return dis[T]>-inf;
    }
    void mcf(){
        int t=T;ll k=inf;
        while(t){
            t=p[t];k=min(k,G[t].cap);t=G[t].flom;
        }
        t=T;ll c=0;
        while(t){
            t=p[t];c+=G[t].cost;G[t].cap-=k;G[t^1].cap+=k;t=G[t].flom;
        }
        if(cost+c*k>=0){
            ans+=k;cost+=c*k;
        }else{
            k=cost/(-c);
            ans+=k;
            printf("%d
    ",ans/2);
            exit(0);
        }
    }
    int main(){
        scanf("%d",&n);S=0,T=1;
        for(int i=1;i<=n;++i)scanf("%d",&a[i]);
        for(int i=1;i<=n;++i)scanf("%d",&b[i]);
        for(int i=1;i<=n;++i)scanf("%d",&c[i]);
        for(int i=1;i<=n;++i)ins(S,i<<1,b[i],0);
        for(int i=1;i<=n;++i)ins(i<<1|1,T,b[i],0);
        for(int i=1;i<=n;++i)
            for(int j=i+1;j<=n;++j)
                if((a[i]%a[j]==0||a[j]%a[i]==0)&&a[i]!=a[j]){
                    int k=a[i]>a[j]?a[i]/a[j]:a[j]/a[i];
                    if(check(k))ins(i<<1,j<<1|1,inf,1ll*c[i]*c[j]),ins(j<<1,i<<1|1,inf,1ll*c[i]*c[j]);
                }
        while(spfa())mcf();
        printf("%d
    ",ans/2);
    }
    View Code
  • 相关阅读:
    两个51相互之间单片机如何进行串口通信
    (stm32f103学习总结)—stm32pwm
    (stm32f103学习总结)—stm32 PMW输出实验
    cpu指令如何读写硬盘
    线程进程同步
    stm32+lwip
    opc
    open62541-server编程
    linux 下time函数
    close与shutdown
  • 原文地址:https://www.cnblogs.com/117208-/p/5381505.html
Copyright © 2011-2022 走看看