ACM-ICPC 2018 焦作赛区网络预赛 F Modular Production Line 最大费用最大流

题目链接
题目描述
An automobile factory has a car production line. Now the market is oversupply and the production line is often shut down. To make full use of resources, the manager divides the entire production line into N parts (1…N). Some continuous parts can produce sub-products. And each of sub-products has their own value. The manager will use spare time to produce sub-products to make money. Because of the limited spare time, each part of the production line could only work at most K times. And Because of the limited materials, each of the sub-products could be produced only once. The manager wants to know the maximum value could he make by produce sub-products.

输入
The first line of input is T, the number of test case.
The first line of each test case contains three integers, N, K and M.(M is the number of different sub-product).
The next M line each contain three integers Ai, Bi, Wi describing a sub-product. The sub-product has value Wi. Only Ai to Bi parts work simultaneously will the sub-product be produced(include Ai to Bi).

1 ≤ T ≤ 100
1 ≤ K ≤ M ≤ 200
1 ≤ N ≤ 10^5
1 ≤ Ai ≤ Bi ≤ N
1 ≤ Wi ≤10^5

输出
For each test case output the maximum value in a separate line.

题目大意:
给你n个部件,每个部件最多用k次,现在有m种组装子部件的方式可以赚得额外的权值,但是每种方法最多只会被用一次。组装子部件需要ai,bi两个部件(两个都会被用一次),可以得到wi的价值。

分析:
有的博主说这是:最长 k 可重区间集问题。。。。。。。
tcl(太菜了),没有听说过,但是这一道题目和P3980 [NOI2008]志愿者招募比较像

先说说这一道题目吧,如果上面那一道弄清楚之后,这一道就会简单许多。
思路差不多,首先肯定要有一个超级汇点t和超级源点s,那么这就需要去建边了,怎么建呢,那就需要从第i到第i+1建立一个容量为INF,花费为0的边;
然后s向第一个点建立一个容量为k,花费为0的边;
最后一个点向t建立一个容量为k,花费为0的边;

这样就保证了流水线的部分最多工作K次;
然后生产需要流水线的区间了,对权值为w的区间[u,v],加边id(u)->id(v+1),容量为1,费用为w就好了;
虽然这样保证了每一个子产品都是生产一次,但是这样求出的是最小值,怎么办呢,我处理的办法是最小费用套用的是spfa的板子,将它改成求最大cost的板子就好了
在这里插入图片描述
还有另外一个建边的方法https://www.cnblogs.com/xiuwenli/p/9651790.html
其实是大同小异啦

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<string>
#include<cmath>
#include<cstring>
#include<set>
#include<queue>
#include<stack>
#include<map>
#define rep(i,a,b) for(int i=a;i<=b;i++)
typedef long long ll;
using namespace std;
const int N=2e5+10;
const ll INF=0x3f3f3f3f3f3f3f3f;
struct node{
    ll from,to,cap,flow,cost;
};
int n,m,s,t,k;
ll day;
vector<node>edge;
vector<int >G[N];
vector<ll>ve;
struct edg{
    ll u,v,w;
}num[300];
ll get_id(int x){
    return lower_bound(ve.begin(),ve.end(),x)-ve.begin()+1;
}
ll a[N],d[N],p[N];
bool inq[N];
void add(ll from,ll to,ll cap,ll cost){
    edge.push_back((node){from,to,cap,0,cost});
    edge.push_back((node){to,from,0 ,0,-cost});
    int cnt=edge.size();
    G[from].push_back(cnt-2);
    G[to].push_back(cnt-1);
}
bool spfa(ll &flow,ll &cost){
    for(int i=0;i<=t+10;i++) d[i]=-INF;
    memset(inq,0,sizeof inq);
    d[s]=0;inq[s]=1;p[s]=0;a[s]=INF;
    queue<int>q;
    q.push(s);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        inq[u]=0;
        for(int i=0;i<G[u].size();i++){
            node e=edge[G[u][i]];
        if(e.cap>e.flow && d[e.to]<d[u]+e.cost){
            d[e.to]=d[u]+e.cost;
            p[e.to]=G[u][i];
            a[e.to]=min(a[u],e.cap-e.flow);
            if(!inq[e.to]){
                q.push(e.to);
                inq[e.to]=1;
            }
          }
        }
    }
    if(d[t] == -INF) return false;
//    cout<<d[t]<<" "<<a[t]<<endl;
    flow += a[t];
    cost+=d[t] * a[t];
    int u=t;
    while(u !=s){
        edge[p[u]].flow +=a[t];
        edge[p[u]^1].flow -=a[t];
        u=edge[p[u]].from;
    }
    return true;
}
ll mincost(){
   ll flow=0;ll cost=0;
   int cnt=0;
    while(spfa(flow,cost));
        return cost;
}
void init(){
    for(int i=0;i<=1000;i++) G[i].clear(),p[i]=0,a[i]=0;
    edge.clear();
    ve.clear();
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif // ONLINE_JUDGE
    int T;
    scanf("%d",&T);
    while(T--){
    scanf("%d%d%d",&n,&k,&m);

    init();
    for(int i=1;i<=m;i++){
        scanf("%lld%lld%lld",&num[i].u,&num[i].v,&num[i].w);
        ve.push_back(num[i].v);
        ve.push_back(num[i].u);
    }
    sort(ve.begin(),ve.end());
    ve.erase(unique(ve.begin(),ve.end()),ve.end());
//    cout<<ve.size()<<endl;
    s=0;t=ve.size()+2;
    for(int i=1;i<=ve.size();i++)
    add(i,i+1,INF,0);

    add(s,1,k,0);
    add(ve.size()+1,t,k,0);

    for(int i=1;i<=m;i++){
        ll u=get_id(num[i].u);
        ll v=get_id(num[i].v);

        add(u,v+1,1,num[i].w);
    }

    printf("%lld\n",mincost());
    }
    return 0;
}


发布了229 篇原创文章 · 获赞 17 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/c___c18/article/details/98478042