• [Ceoi2008]order


    Description

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

    Input

    第一行给出 N,M(1<=N<=1200,1<=M<=1200) 下面将有N块数据,每块数据第一行给出完成这个任务能赚到的钱(其在[1,5000])及有多少道工序 接下来若干行每行两个数,分别描述完成工序所需要的机器编号及租用它的费用(其在[1,20000]) 最后M行,每行给出购买机器的费用(其在[1,20000])

    Output

    最大利润

    Sample Input

    2 3
    100 2
    1 30
    2 20
    100 2
    1 40
    3 80
    50
    80
    110

    Sample Output

    50

    Solution

    这个,非常明显的一道最大权闭合子图。就是有一个租用机器的操作非常的让人不舒服。然后想想,我们这图里面的inf边是不是还可以再利用一下,于是把inf改成了租用机器的价格。很容易发现这个满足流量平衡的要求。然后,就没了。

    Code

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #define re register
    #define inf 400000000
    #define MAXN 2500
    #define MAXM 5000000
    using namespace std;
    int n,s,q,t,l,cur[200051];
    struct po
    {
        int nxt,to,w;
    }edge[MAXM];
    int head[MAXN],dep[MAXN],num=-1,tot,m;
    inline int read()
    {
        int x=0,c=1;
        char ch=' ';
        while((ch>'9'||ch<'0')&&ch!='-')ch=getchar();
        while(ch=='-')c*=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
        return x*c;
    }
    inline void add_edge(int from,int to,int w)
    {
        edge[++num].nxt=head[from];
        edge[num].to=to;
        edge[num].w=w;
        head[from]=num;
    }
    inline void add(int from,int to,int w)
    {
        add_edge(from,to,w);
        add_edge(to,from,0);
    }
    inline bool bfs()
    {
        memset(dep,0,sizeof(dep));
        queue<int> q;
        while(!q.empty())
        q.pop();
        q.push(s);
        dep[s]=1;
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(re int i=head[u];i!=-1;i=edge[i].nxt)
            {
                int v=edge[i].to;
                if(dep[v]==0&&edge[i].w>0)
                {
                    dep[v]=dep[u]+1;
                    if(v==t)
                    return 1;
                    q.push(v);
                }
            }
        }
        return 0;
    }
    inline int dfs(int u,int dis)
    {
        if(u==t)
        return dis;
        int diss=0;
        for(re int& i=cur[u];i!=-1;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(edge[i].w!=0&&dep[v]==dep[u]+1)
            {
                int check=dfs(v,min(dis,edge[i].w));
                if(check>0)
                {
                    dis-=check;
                    diss+=check;
                    edge[i].w-=check;
                    edge[i^1].w+=check;
                    if(dis==0) break;
                }
            }
        }
        return diss;
    }
    inline int dinic()
    {
        int ans=0;
        while(bfs())
        {
            for(re int i=0;i<=t;i++)
            cur[i]=head[i];
            while(int d=dfs(s,inf))
            ans+=d;
        }
        return ans;
    }
    int main() 
    {
        memset(head,-1,sizeof(head));
        n=read();m=read();
        s=0;t=n+m+1;
        for(re int i=1;i<=n;i++){
        	int raise=read(),x=read();
        	tot+=raise;
        	add(s,i,raise);
        	for(re int j=1;j<=x;j++){
        		int v=read(),cost=read();
        		add(i,n+v,cost);
        	}
        }
        
        for(re int i=1;i<=m;i++)
            add(i+n,t,read());
        cout<<tot-dinic();
        return 0;
    }
    
  • 相关阅读:
    P4665 [BalticOI 2015]Network 题解
    NOIp2020游记
    独立集(bubble) 题解
    密码(substring) 题解
    8.20被题虐
    开通博客了!
    CSP-S2021 记
    「CSP-S 2020」函数调用(拓扑排序+DP)
    OI生涯回忆录
    [UOJ79]一般图最大匹配(带花树)
  • 原文地址:https://www.cnblogs.com/victorique/p/9139575.html
Copyright © 2020-2023  润新知