版权声明: https://blog.csdn.net/yyy_3y/article/details/82724970
传送门
题意:有一个流水线,一共有n个独立工厂,给你m个产品,每个产品需经过
到
才能获得其价值
。每次产品最多只能得到一次价值。每个独立工厂最多只能工作k次,问获得的最大价值。
思路:区间k覆盖模型。是网络流24题的经典模型之一,最大费用最大流。
1)N=1e5,需要离散化。
2)建立源点和汇点S,T。从S连边到第一个点(最小),流量为k,花费为0。
3)每两个点之间连边流量为inf,花费为0。
4)对于每条给出的边连边,流量为1(因为,而每个产品最多只能得到一次价值),花费为给我的-
。
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;
}