• 「CEOI2008」order


    题目链接

    戳我

    (Solution)

    首先看看没有租条件的怎么弄.这很显然,就是普通最小割的套路
    (s)向每个工作连一条流量(x)的边,(x)为工作收益
    每个工作向每个机器连流量为(inf)的边
    每个机器向(T)连流量为(v)的费用,(v)为买机器的费用
    跑一遍最小割
    答案就是(sum x-Dinic())
    至于如果有租的条件,我们只需要将(inf)变成租的费用就好了

    (Code)

    #include<bits/stdc++.h>
    #define file(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
    using namespace std;
    const int inf=1e9;
    typedef long long ll;
    inline int read(){
        int x=0,f=1;char c=getchar();
        while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
        while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
        return x*f;
    }
    struct node{
        int to,next,v;
    }a[9000001];
    int head[3410],cnt=1,n,m,s,t,x,y,z,dep[3410],sum,cur[3410];
    inline void add(int x,int y,int c){
        a[++cnt].to=y,a[cnt].next=head[x],a[cnt].v=c,head[x]=cnt;
        a[++cnt].to=x,a[cnt].next=head[y],a[cnt].v=0,head[y]=cnt;
    }
    queue<int> q;
    inline int bfs(){
        memset(dep,0,sizeof(dep)),q.push(s),dep[s]=1;
        while(!q.empty()){
            int now=q.front();
            q.pop();
            for(int i=head[now];i;i=a[i].next){
                int v=a[i].to;
                if(!dep[v]&&a[i].v>0)
                    dep[v]=dep[now]+1,q.push(v);
            }
        }
        return dep[t];
    }
    int dfs(int k,int list) {
        if(k==t||!list)
            return list;
        int flow=0;
        for(int i=head[k];i;i=a[i].next){
            int v=a[i].to;
            if(dep[v]==dep[k]+1&&a[i].v>0){
                int p=dfs(v,min(list,a[i].v));
                if(p){
                    list-=p,flow+=p,a[i].v-=p,a[i^1].v+=p;
                    if(!list)
                        break;
                }
            }
        }
        return flow;
    }
    void Dinic(){
        int ans=0,k;
        while(bfs())
    		ans+=dfs(s,inf);
        printf("%d",sum-ans);
    }
    int main(){
        n=read(),m=read(),s=0,t=n+m+1;
        for(int i=1;i<=n;i++){
            x=read(),add(s,i,x),sum+=x,y=read();
            while(y--)
                x=read(),z=read(),add(i,x+n,z);
        }
        for(int i=1;i<=m;i++)
            x=read(),add(i+n,t,x);
        Dinic();
    }
    
  • 相关阅读:
    期中考试补完计划
    c++简单程序设计-4
    c++简单程序设计-3
    c++简单程序设计-2
    c++简单程序设计-1
    layer ifram 弹出框
    定时发邮件
    二维码生成
    文件或文件夹的压缩
    excel 导入 与 导出
  • 原文地址:https://www.cnblogs.com/hbxblog/p/11228553.html
Copyright © 2020-2023  润新知