ACM-ICPC 2018 焦作赛区网络预赛_F_ Modular Production Line_费用流

版权声明: https://blog.csdn.net/yyy_3y/article/details/82724970

传送门
题意:有一个流水线,一共有n个独立工厂,给你m个产品,每个产品需经过 A i A_i B i B_i 才能获得其价值 W i W_i 。每次产品最多只能得到一次价值。每个独立工厂最多只能工作k次,问获得的最大价值。
思路:区间k覆盖模型。是网络流24题的经典模型之一,最大费用最大流。
1)N=1e5,需要离散化。
2)建立源点和汇点S,T。从S连边到第一个点(最小),流量为k,花费为0。
3)每两个点之间连边流量为inf,花费为0。
4)对于每条给出的边连边,流量为1(因为,而每个产品最多只能得到一次价值),花费为给我的- W i W_i
5)最后一个点向T连边,流量为k,费用为0。

#include<bits/stdc++.h>
#define LL long long
#define ULL unsigned long long
#define UINT unsigned LL
#define MAXN (100000+100)
#define lnn putchar('\n')
#define see putchar(' ')
using namespace std;
const int maxn=1e5+7;
const int MOD=1e9+7;
const int M=1000001;
const int N=5500;
const int inf=0x3f3f3f3f;
int head[N],n,m,cnt;
struct node{
    LL to,cap,money,next;
}edge[M];
struct MCMF{
    int len[N];
    int pre[N];
    int path[N];
    bool vis[N];
    void init()
    {
        memset(head,-1,sizeof head);
        cnt=0;
    }
    void add(int u,int v,int cap,int money)
    {
        edge[cnt].to=v;
        edge[cnt].cap=cap;
        edge[cnt].next=head[u];
        edge[cnt].money=money;
        head[u]=cnt++;

        edge[cnt].to=u;
        edge[cnt].cap=0;
        edge[cnt].next=head[v];
        edge[cnt].money=-money;
        head[v]=cnt++;
    }
    bool spfa(int s,int t)
    {
        memset(vis,false,sizeof vis);
        memset(pre,-1,sizeof pre);
        memset(path,-1,sizeof path);
        memset(len,inf,sizeof len);
        queue<LL> q;
        q.push(s);
        vis[s]=true;
        len[s]=0;
        while(!q.empty()){
            LL u=q.front();
            q.pop();
            vis[u]=false;
            for(int i=head[u];i!=-1;i=edge[i].next){
                int v=edge[i].to;
                if(len[v]>len[u]+edge[i].money && edge[i].cap>0){
                    len[v]=len[u]+edge[i].money;
                    pre[v]=u;
                    path[v]=i;
                    if(!vis[v]){
                        vis[v]=true;
                        q.push(v);
                    }
                }
            }
        }
        return len[t]!=inf;
    }
    LL MinCostMaxFlow(LL s,LL t)
    {
        LL sum=0;
        while(spfa(s,t)){
            LL mmin=inf;
            for(LL i=t;i!=s && i!=-1;i=pre[i]){
                mmin=min(mmin,edge[path[i]].cap);

            }
           for(LL i=t;i!=s && i!=-1;i=pre[i]){
                edge[path[i]].cap-=mmin;
                edge[path[i]^1].cap+=mmin;
            }
            sum+=mmin*(len[t]);
        }
        return sum;
    }
};
int xx[N],yy[N],zz[N],cl[N];
vector<int> num;
int tot=0;
int main()
{
    MCMF mcmf;
    LL T;
    for(scanf("%lld",&T);T--;){
        num.clear();
        tot=0;
        mcmf.init();
        int k,m,n; scanf("%d%d%d",&n,&k,&m);
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&xx[i],&yy[i],&zz[i]);
            yy[i]++;
            num.push_back(xx[i]);
            num.push_back(yy[i]);
        }
        sort(num.begin(),num.end());
        int cnt=unique(num.begin(),num.end())-num.begin();
        int S=0,T=cnt+1;
        for(int i=0;i<cnt;i++){
            cl[i]=++tot;
        }
        mcmf.add(S,cl[0],k,0);
        for(int i=0;i<cnt-1;i++){
            mcmf.add(cl[i],cl[i+1],inf,0);

        }
        for(int i=1;i<=m;i++){
            int a=lower_bound(num.begin(),num.begin()+cnt,xx[i])-num.begin();
            int b=lower_bound(num.begin(),num.begin()+cnt,yy[i])-num.begin();
            mcmf.add(cl[a],cl[b],1,-zz[i]);
        }
        mcmf.add(cl[cnt-1],T,k,0);
        printf("%lld\n",-mcmf.MinCostMaxFlow(S,T));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yyy_3y/article/details/82724970