题目
费用流建出来大概是下面的图(没有写边权的边都是容量 ∞ \infty ∞,费用为 0 0 0)
所以这个图有 4 4 4种流法(其实有 5 5 5种,但是第 5 5 5种在实际实现中可以被这 4 4 4种覆盖。)
1. 1. 1.类似于 A → D → D ′ → J A \rightarrow D \rightarrow D' \rightarrow J A→D→D′→J的流,直接把 a i + b i a_i+b_i ai+bi选中。
2. 2. 2.类似于 A → D → F → G → C ′ → J A\rightarrow D \rightarrow F \rightarrow G\rightarrow C'\rightarrow J A→D→F→G→C′→J的流,选 a i a_i ai中最大和 b i b_i bi中最大的值匹配,显然两边最大值位置相同时 1 1 1比 2 2 2要更优秀,此时走 1 1 1不走 2 2 2,尽管我们的费用是一样的,这样写的好处是费用流的流就不会有让你走 0 0 0环来给 F → G F\rightarrow G F→G退流的情况,可以少几类讨论。
3 , 4. 3,4. 3,4.都是带有退流的性质,具体就是如果 C ′ → J C'\rightarrow J C′→J被流了,那么我们用 C C C配上 C ′ C' C′然后通过 C ′ → G C'\rightarrow G C′→G退流回去让原来的和 C ′ C' C′匹配的点 X X X另找一个配对点再走一个类似 G → E ′ G \rightarrow E' G→E′的路径,注意如果另外找的配对点是 X ′ X' X′,我们就要顺便把 F → G F\rightarrow G F→G退流,以此来避免走 0 0 0环。
4 4 4是 3 3 3在 A A A这一侧的类似情况。
然后注意写 s e t set set是怎么卡都过不了的。
写优先队列模拟堆即可。
A C C o d e \mathcal AC \ Code AC Code
#include
#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
#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);
}
}