zoukankan      html  css  js  c++  java
  • LOJ6045 雅礼集训 2017 Day8 价(最小割)

      由Hall定理,任意k种减肥药对应的药材数量>=k。考虑如何限制其恰好为k,可以将其看作是使对应的药材数量尽量少。

      考虑最小割。建一个二分图,左边的点表示减肥药,右边的点表示药材。减肥药和其使用的药材连inf边,这里的inf边较大,可以取到1e18;源向减肥药连inf-pi的边,表示不选这种减肥药会损失pi,这里的inf边较小,可以取到1e9;药材向汇连1e9的inf边,用来限制药材数量。容易发现最后的最小割中至少会割掉n条边,且割掉的边越少越优,而当恰好割掉n条边时,就对应了一种减肥药与药材数量相等的方案。直接跑最小割即可。这是一种针对多级限制的思想。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 610
    #define S 0
    #define T 601
    #define inf 1000000000
    #define INF 1000000000000000000ll
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int n,a[N],p[N],d[N],cur[N],q[N],t=-1;
    ll ans;
    struct data{int to,nxt;ll cap,flow;
    }edge[N*N<<2];
    void addedge(int x,int y,ll z)
    {
        t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].cap=z,p[x]=t;
        t++;edge[t].to=x,edge[t].nxt=p[y],edge[t].cap=0,p[y]=t;
    }
    bool bfs()
    {
        memset(d,255,sizeof(d));d[S]=0;
        int head=0,tail=1;q[1]=S;
        do
        {
            int x=q[++head];
            for (int i=p[x];~i;i=edge[i].nxt)
            if (d[edge[i].to]==-1&&edge[i].flow<edge[i].cap)
            {
                d[edge[i].to]=d[x]+1;
                q[++tail]=edge[i].to;
            }
        }while (head<tail);
        return ~d[T];
    }
    ll work(int k,ll f)
    {
        if (k==T) return f;
        ll used=0;
        for (int i=cur[k];~i;i=edge[i].nxt)
        if (d[k]+1==d[edge[i].to])
        {
            ll w=work(edge[i].to,min(f-used,edge[i].cap-edge[i].flow));
            edge[i].flow+=w,edge[i^1].flow-=w;
            if (edge[i].flow<edge[i].cap) cur[k]=i;
            used+=w;if (used==f) return f;
        }
        if (used==0) d[k]=-1;
        return used;
    }
    void dinic()
    {
        while (bfs())
        {
            memcpy(cur,p,sizeof(p));
            ans-=work(S,INF);
        }
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("loj6045.in","r",stdin);
        freopen("loj6045.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read();
        memset(p,255,sizeof(p));
        for (int i=1;i<=n;i++)
        {
            int m=read();
            while (m--)
            {
                int x=read();
                addedge(i,n+x,INF);
            }
        }
        for (int i=1;i<=n;i++) a[i]=read();
        for (int i=1;i<=n;i++) addedge(S,i,inf-a[i]),ans+=inf-a[i];
        for (int i=1;i<=n;i++) addedge(n+i,T,inf);
        dinic();
        cout<<-ans;
        return 0;
    }
  • 相关阅读:
    1063. Set Similarity
    A1047. Student List for Course
    A1039. Course List for Student
    最大公约数、素数、分数运算、超长整数计算总结
    A1024. Palindromic Number
    A1023. Have Fun with Numbers
    A1059. Prime Factors
    A1096. Consecutive Factors
    A1078. Hashing
    A1015. Reversible Primes
  • 原文地址:https://www.cnblogs.com/Gloid/p/10250417.html
Copyright © 2011-2022 走看看