题目
费用流建出来大概是下面的图(没有写边权的边都是容量
,费用为
)
所以这个图有
种流法(其实有
种,但是第
种在实际实现中可以被这
种覆盖。)
类似于
的流,直接把
选中。
类似于
的流,选
中最大和
中最大的值匹配,显然两边最大值位置相同时
比
要更优秀,此时走
不走
,尽管我们的费用是一样的,这样写的好处是费用流的流就不会有让你走
环来给
退流的情况,可以少几类讨论。
都是带有退流的性质,具体就是如果
被流了,那么我们用
配上
然后通过
退流回去让原来的和
匹配的点
另找一个配对点再走一个类似
的路径,注意如果另外找的配对点是
,我们就要顺便把
退流,以此来避免走
环。
是
在
这一侧的类似情况。
然后注意写
是怎么卡都过不了的。
写优先队列模拟堆即可。
#include<bits/stdc++.h>
#define maxn 200005
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define pii pair<int,int>
#define mp make_pair
#define LL long long
#define Fi first
#define Se second
#define inf 0x3f3f3f3f
using namespace std;
int n,K,L,a[maxn],b[maxn];
int usa[maxn],usb[maxn];
priority_queue<pii >Ha,Hb,Fa,Fb,G;
char cb[1<<16],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<16,stdin),cs==ct)?0:*cs++)
void read(int &res){
char ch;
for(;!isdigit(ch=getc()););
for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0');
}
int main(){
freopen("sequence.in","r",stdin);
freopen("sequence.out","w",stdout);
int T;read(T);
for(;T--;){
read(n),read(K),read(L);
for(;!Ha.empty();Ha.pop());
for(;!Hb.empty();Hb.pop());
for(;!Fa.empty();Fa.pop());
for(;!Fb.empty();Fb.pop());
for(;!G.empty();G.pop());
rep(i,1,n) usa[i] = usb[i] = 0;
rep(i,1,n) read(a[i]),Ha.push(mp(a[i],i));
rep(i,1,n) read(b[i]),Hb.push(mp(b[i],i)),G.push(mp(a[i]+b[i],i));
LL ans = 0;int stC = K-L;
rep(Tim,1,K){
for(;!Ha.empty() && usa[Ha.top().Se];Ha.pop());
for(;!Hb.empty() && usb[Hb.top().Se];Hb.pop());
for(;!Fa.empty() && usa[Fa.top().Se];Fa.pop());
for(;!Fb.empty() && usb[Fb.top().Se];Fb.pop());
for(;!G.empty() && (usa[G.top().Se] || usb[G.top().Se]);G.pop());
if(stC){
int x = (Ha.top()).Se , y = (Hb.top()).Se;
ans += a[x] + b[y];
stC--;
usa[x] = 1;
if(!usb[x]) Fb.push(mp(b[x],x));
else stC++;
usb[y] = 1;
if(!usa[y]) Fa.push(mp(a[y],y));
else stC++;
}
else{
int A = (G.empty() ? -inf : (G.top()).Fi) , B = (Fa.empty() ? -inf : (Fa.top()).Fi) + (Hb.top()).Fi , C = (Ha.top()).Fi + (Fb.empty() ? -inf : (Fb.top()).Fi);
if(A >= B && A >= C){
ans += A;
int t = (G.top()).Se;
usa[t] = usb[t] = 1;
}
else if(B >= A && B >= C){
ans += B;
int x = (Fa.top()).Se , y = (Hb.top()).Se;
if(usa[y]) stC++;
else Fa.push(mp(a[y],y));
usa[x] = usb[y] = 1;
}
else{
ans += C;
int x = (Fb.top()).Se , y = (Ha.top()).Se;
if(usb[y]) stC++;
else Fb.push(mp(b[y],y));
usb[x] = usa[y] = 1;
}
}
}
printf("%lld\n",ans);
}
}