P4177 [CEOI2008]order

P4177 [CEOI2008]order

题目描述

有N个工作,M种机器,每种机器你可以租或者买过来. 每个工作包括若干道工序,每道工序需要某种机器来完成,你可以通过购买或租用机器来完成。 现在给出这些参数,求最大利润

输入输出格式

输入格式:

第一行给出 N,M(1<=N<=1200,1<=M<=1200) 下面将有N组数据。

每组数据第一行给出完成这个任务能赚到的钱(其在[1,5000])及有多少道工序

接下来若干行每行两个数,分别描述完成工序所需要的机器编号及租用它的费用(其在[1,20000]) 最后M行,每行给出购买机器的费用(其在[1,20000])

输出格式:

最大利润



若是没有租用一说,本题即为最大权闭合子图求最小割。

当有租用的时候,我们仍按照最大权闭合子图构建模型,与之前不同的是,有关系的两点连边容边不再是INF而是租用费用

我们仍可以用之前的解释:要么舍弃报酬(即正权点),要么买器材(负权点);租用怎么办呢?对于一个实验,我们有了除了之前两种方案的(即不做工作或购买机器)的第三种选择,租用,所以在求最小割的时候,我们要么割断源点到正权之间的边(不做这项工作),要么割断负权到汇点之间的边(买机器),要么割断中间的边(在一个工作中租用仪器),求得的最小割即为舍弃的最小利益

所以最优答案即为 总利益 - 舍弃的最小利益

Code

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
typedef long long ll;
using namespace std;
int RD(){
    int out = 0,flag = 1;char c = getchar();
    while(c < ‘0‘ || c >‘9‘){if(c == ‘-‘)flag = -1;c = getchar();}
    while(c >= ‘0‘ && c <= ‘9‘){out = out * 10 + c - ‘0‘;c = getchar();}
    return flag * out;
    }
const int maxn = 1000019,INF = 1e9;
int numw,numm;
int head[maxn],nume = 1;
struct Node{
    int v,dis,nxt;
    }E[maxn << 3];
void add(int u,int v,int dis){
    E[++nume].nxt = head[u];
    E[nume].v = v;
    E[nume].dis = dis;
    head[u] = nume;
    }
int maxflow,s,t;
int d[maxn];
bool bfs(){
    queue<int>Q;
    memset(d,0,sizeof(d));
    d[s] = 1;
    Q.push(s);
    while(!Q.empty()){
        int u = Q.front();Q.pop();
        for(int i = head[u];i;i = E[i].nxt){
            int v = E[i].v;
            if(!d[v] && E[i].dis){
                d[v] = d[u] + 1;
                Q.push(v);
                if(v == t)return 1;
                }
            }
        }
    return 0;
    }
int Dinic(int u,int flow){
    if(u == t)return flow;
    int rest = flow,k;
    for(int i = head[u];i;i = E[i].nxt){
        int v = E[i].v;
        if(d[v] == d[u] + 1 && E[i].dis){
            k = Dinic(v,min(rest,E[i].dis));
            if(!k)d[v] = 0;
            E[i].dis -= k;
            E[i ^ 1].dis += k;
            rest -= k;
            }
        if(!rest)break;
        }
    return flow - rest;
    }
int tot;
int main(){
    s = 0, t = 10026;
    numw = RD();numm = RD();
    for(int i = 1;i <= numw;i++){
        int money = RD(), num = RD();
        tot += money;
        add(s, i << 1, money);add(i << 1, s, 0);
        for(int j = 1;j <= num;j++){
            int index = RD(), rent = RD();
            add(i << 1, index << 1 | 1, rent);
            add(index << 1 | 1, i << 1, 0);
            }
        }
    for(int i = 1;i <= numm;i++){
        int money = RD();
        add(i << 1 | 1, t, money);
        add(t, i << 1 | 1, 0);
        }
    int flow = 0;
    while(bfs())while(flow = Dinic(s,INF))maxflow += flow;
    printf("%d\n",tot - maxflow);
    return 0;
    }

原文地址:https://www.cnblogs.com/Tony-Double-Sky/p/9285939.html

时间: 2024-11-22 23:52:24

P4177 [CEOI2008]order的相关文章

BZOJ 1391: [Ceoi2008]order [最小割]

1391: [Ceoi2008]order Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1509  Solved: 460[Submit][Status][Discuss] Description 有N个工作,M种机器,每种机器你可以租或者买过来. 每个工作包括若干道工序,每道工序需要某种机器来完成,你可以通过购买或租用机器来完成. 现在给出这些参数,求最大利润 Input 第一行给出 N,M(1<=N<=1200,1<=M<=12

BZOJ1391: [Ceoi2008]order

1391: [Ceoi2008]order Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 534  Solved: 170[Submit][Status] Description 有N个工作,M种机器,每种机器你可以租或者买过来. 每个工作包括若干道工序,每道工序需要某种机器来完成,你可以通过购买或租用机器来完成. 现在给出这些参数,求最大利润 Input 第一行给出 N,M(1<=N<=1200,1<=M<=1200) 下面将有N块

[Luogu4177][CEOI2008]order

luogu sol 这题有点像网络流24题里面的太空飞行计划啊. 最大收益=总收益-最小损失. 先令\(ans=\sum\)任务收益. 源点向每个任务连容量为收益的边. 每个机器向汇点连容量为购买费用的边. 每个任务向对应的机器连容量为租赁费用的边. 最小割即可. code 在\(bfs\)里面用了一个玄学卡常技巧.并没有什么用 #include<cstdio> #include<algorithm> #include<cstring> #include<queu

最小割 --- [CEOI2008]order

[CEOI2008]order 题目描述: 有N个任务,M种机器,每种机器你可以租或者买过来. 每个工作包括若干道工序,每道工序需要某种机器来完成,你可以通过购买或租用机器来完成. 现在给出这些参数,求最大利润 输入格式: 第一行给出 N, M (1 <= N <= 1200, 1 <= M <= 1200) 下面将有N个任务的数据. 每组数据第一行给出完成这个任务能赚到的钱([1,5000])及有多少道工序 接下来若干行每行两个数,分别描述完成工序所需要的机器编号及租用它的费用(

BZOJ 1391: [Ceoi2008]order

Description 有一些任务,需要用到一些机器,可以买可以租,问最大获利. Solution 网络流. 最大权闭合子图模型. 建图很简单就是S->机器,机器->任务,任务->T. 如果没有租用的话,中间的是INF,不会割掉,加上租用就把容量变成租用的价格即可. 这样求出来的割就是最小损失了,用总数减去即可. Code /************************************************************** Problem: 1391 User:

1391: [Ceoi2008]order

有N个工作,M种机器,每种机器你可以租或者买过来. 每个工作包括若干道工序,每道工序需要某种机器来完成,你可以通过购买或租用机器来完成. 现在给出这些参数,求最大利润 Input 第一行给出 N,M(1<=N<=1200,1<=M<=1200) 下面将有N块数据,每块数据第一行给出完成这个任务能赚到的钱(其在[1,5000])及有多少道工序 接下来若干行每行两个数,分别描述完成工序所需要的机器编号及租用它的费用(其在[1,20000]) 最后M行,每行给出购买机器的费用(其在[1,

[CEOI2008]order

Description 有N个工作,M种机器,每种机器你可以租或者买过来. 每个工作包括若干道工序,每道工序需要某种机器来完成,你可以通过购买或租用机器来完成. 现在给出这些参数,求最大利润 Solution 相对于最大权闭合子图,多了一个租用操作 实际上把中间的\(inf\)边改成租用的费用就可以了 这样要么割在\(S\)的出边,要么割在中间,要么割在\(T\)的入边了 分别对应舍弃这种物品的利润,租用和购买了 #include<bits/stdc++.h> using namespace

【BZOJ-1391】order 最小割 + 最大全闭合图

1391: [Ceoi2008]order Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1334  Solved: 405[Submit][Status][Discuss] Description 有N个工作,M种机器,每种机器你可以租或者买过来. 每个工作包括若干道工序,每道工序需要某种机器来完成,你可以通过购买或租用机器来完成.现在给出这些参数,求最大利润 Input 第一行给出 N,M(1<=N<=1200,1<=M<=120

一些简单的网络流模型

一.最大权闭合图 对于一个图(V, E)由点集V和一些有向边集E组成,每个点有一定权值,对于一个合法子集,若有一条有向边(u,v)并且u在子集中,则v也必须在子集中,求子集中所有元素权值和最大的子集 分析:考虑每个点有两种状况,选和不选,所以考虑最小割,但是要求最大费用: 先假设取了所有正权点,从原点向所有正权点连边,从所有负权点向汇点连边,容量为权值的绝对值, 对于一个割[S,T](S内的点表示选择了的点), 正权点在S内,表示选了这个点,与S相连的边没有被割,若在T内,表示这个点被割则被割,