题目链接
题目描述
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;
}