• 题解 洛谷 P4177 【[CEOI2008]order】


    进行分析后,发现最大收益可以转化为最小代价,那么我们就可以考虑用最小割来解决这道题。

    先算出总收益(sum),总收益减去最小代价即为答案。

    然后考虑如何建图,如何建立最小割的模型。

    发现一个任务最终的处理只有两种情况:

    ① 不完成这个任务,那么我们需要支付(val)的代价。

    ② 完成这个任务,若任务中某个工序用租的方式来解决,则需要支付其租金的代价,若用买的方式来解决,则需要支付其购买费用的代价,且以后可以使用这台机器。

    那么最小割的模型就可以建立了。

    从源点(S)向每个任务连边,容量为收益(val),割边表示不完成这个任务。

    从每个任务向其所对应的机器连边,容量为租金,割边表示租机器来完成工序。

    从每个机器向汇点(T)连边,容量为购买的费用,割边表示购买机器。

    边的数组记得开大,实现细节就看代码吧。

    (code:)

    #include<bits/stdc++.h>
    #define maxn 3000010
    #define inf 200000000
    using namespace std;
    template<typename T> inline void read(T &x)
    {
    	x=0;char c=getchar();bool flag=false;
    	while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
    	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    	if(flag)x=-x;
    }
    int n,m,s,t,sum;
    struct edge
    {
        int to,nxt,v;
    }e[maxn];
    int head[maxn],edge_cnt=1;
    void add(int from,int to,int val)
    {
        e[++edge_cnt]=(edge){to,head[from],val};
        head[from]=edge_cnt;
        e[++edge_cnt]=(edge){from,head[to],0};
        head[to]=edge_cnt;
    }
    int d[maxn],cur[maxn];
    bool bfs()
    {
        for(int i=s;i<=t;++i) cur[i]=head[i];
        memset(d,0,sizeof(d));
        d[s]=1;
        queue<int> q;
        q.push(s);
        while(!q.empty())
        {
            int x=q.front();
            q.pop();
            for(int i=head[x];i;i=e[i].nxt)
            {
                int y=e[i].to,v=e[i].v;
                if(d[y]||!v) continue;
                d[y]=d[x]+1;
                q.push(y);
            }
        }
        return d[t];
    }
    int dfs(int x,int lim)
    {
        if(x==t) return lim;
        int flow,res=lim;
        for(int &i=cur[x];i;i=e[i].nxt)
        {
            int y=e[i].to,v=e[i].v;
            if(d[y]!=d[x]+1||!v) continue;
            if(flow=dfs(y,min(res,v)))
            {
                res-=flow;
                e[i].v-=flow;
                e[i^1].v+=flow;
                if(!res) break;
            }
        }
        return lim-res;
    }
    int dinic()
    {
        int ans=0,flow;
        while(bfs())
            while(flow=dfs(s,inf))
                ans+=flow;
        return ans;
    }
    int main()
    {
        read(n),read(m),t=n+m+1;
        for(int i=1;i<=n;++i)
        {
            int val,k;
            read(val),read(k);
            sum+=val,add(s,i,val);
            for(int j=1;j<=k;++j)
            {
                int num,cost;
                read(num),read(cost);
                add(i,n+num,cost);
            }
        }
        for(int i=1;i<=m;++i)
        {
            int cost;
            read(cost);
            add(n+i,t,cost);
        }
        printf("%d",sum-dinic());
    	return 0;
    }
    
  • 相关阅读:
    EMVTag系列15《选择应用响应数据》
    EMVTag系列14《支付环境响应数据》
    EMVTag系列13《脱机PIN》
    EMVTag系列9《卡片管理数据》
    EMVTag系列7《静态签名数据》
    EMVTag系列6《IAC 发卡行行为代码》
    EMVTag系列2《磁条等效数据》
    code1169 传纸条
    关于 变量越界
    code1039 数的划分
  • 原文地址:https://www.cnblogs.com/lhm-/p/12229869.html
Copyright © 2020-2023  润新知