BZOJ 1391: [Ceoi2008]order

Description

有一些任务,需要用到一些机器,可以买可以租,问最大获利.

Solution

网络流.

最大权闭合子图模型.

建图很简单就是S->机器,机器->任务,任务->T.

如果没有租用的话,中间的是INF,不会割掉,加上租用就把容量变成租用的价格即可.

这样求出来的割就是最小损失了,用总数减去即可.

Code

/**************************************************************
    Problem: 1391
    User: BeiYu
    Language: C++
    Result: Accepted
    Time:3864 ms
    Memory:55972 kb
****************************************************************/

#include <bits/stdc++.h>
using namespace std;

#define debug(a) cout<<#a<<"="<<a<<" "
const int INF = 0x3fffffff;
const int N = 3650;
const int M = 3000500;

inline int in(int x=0,char ch=getchar()) { while(ch>‘9‘ || ch<‘0‘) ch=getchar();
    while(ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();return x; }

int n,m;
int val[N],ned[N],c[N];

struct NetWork {
    vector< int > g[N];
    struct Edge { int fr,to,fl; }edge[M];
    int s,t,cnte,flow,tot;
    int cur[N],d[N],p[N];

    void AddEdge(int fr,int to,int fl) {
        g[fr].push_back(cnte),edge[cnte++]=(Edge){ fr,to,fl };
        g[to].push_back(cnte),edge[cnte++]=(Edge){ to,fr,0 };
    }
    void Build() {
        n=in(),m=in();
        s=0,t=2*m+n+6;
        for(int i=1,x;i<=n;i++) {
            for(x=in(),tot+=x,AddEdge(i,t,x),x=in();x--;) {
                int idx=in(),cost=in();
                AddEdge(n+idx,i,cost);
            }
        }
        for(int i=1;i<=m;i++) {
            c[i]=in();
            int x=n+i;
            AddEdge(s,x,c[i]);
        }
//      for(int i=1;i<=m;i++) cout<<c1[i]<<" "<<c2[i]<<endl;
    }
    int BFS() {
        queue< int > q;
        memset(d,0xff,sizeof(d));
        q.push(s),d[s]=1;
        for(int x;!q.empty();) {
            x=q.front(),q.pop();
            for(int i=0,lm=g[x].size(),v;i<lm;i++) if(edge[g[x][i]].fl && d[(v=edge[g[x][i]].to)]==-1) {
                d[v]=d[x]+1,q.push(v);
            }
        }return d[t]!=-1;
    }
    void Dinic() {
//      debug(s),debug(t)<<endl;
        for(int u,k;BFS();) {
//          cout<<"qwq"<<endl;debug(flow)<<endl;
            for(memset(cur,0,sizeof(cur)),u=s,k=0;;) {
                if(u==t) {
                    int mine=0,minf=INF;
                    for(int i=0;i<k;i++) if(edge[p[i]].fl<minf) minf=edge[p[i]].fl,mine=i;
                    for(int i=0;i<k;i++) edge[p[i]].fl-=minf,edge[p[i]^1].fl+=minf;
//                  for(int i=0;i<k;i++) cout<<edge[p[i]].fr<<"-->";cout<<endl;
//                  debug(minf)<<endl;
                    k=mine,flow+=minf,u=edge[p[mine]].fr;
                }
                for(int &i=cur[u],lm=g[u].size(),v;i<lm;i++)
                    if(edge[g[u][i]].fl && d[(v=edge[g[u][i]].to)]==d[u]+1) break;
                if(cur[u]<(int)g[u].size()) {
                    p[k++]=g[u][cur[u]],u=edge[g[u][cur[u]]].to;
                } else {
                    if(!k) break;
                    d[u]=-1,u=edge[p[--k]].fr;
                }
            }
        }
    }
    int Maxflow() {
        flow=0,tot=0;
        Build();
        Dinic();
        return tot-flow;
    }
}py;

int main() {
    cout<<py.Maxflow()<<endl;
    return 0;
}

  

时间: 2024-10-25 21:04:04

BZOJ 1391: [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

1391: [Ceoi2008]order

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

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])及有多少道工序 接下来若干行每行两个数,分别描述完成工序所需要的机器编号及租用它的费用(

P4177 [CEOI2008]order

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

bzoj 1390: [Ceoi2008]Fence

Description 在一个大小为1000*1000的区域中,有n个固定点,m棵tree . 现在你要建一个围栏来保护tree,建它的费用为你选用的固定点的个数 *20和 你没有圈进围栏的tree*111. 现在希望这个值越小越好. 3<=N<=100. 1<=M<=100 Input 第一行给出n,m 下面开始n行,给出固定的坐标 下面开始m行,给出tree的坐标 Output 输出最小费用 根据题目设定的参数,凡是可以围住的点都要围住,同bzoj1027可以转为最小环 #in

[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