2019 ICPC 南京 J . Spy
题目大意:
a[i]表示对手的每个队伍战斗力
p[i]表示打败对手后获得的分数
b[i]表示我方第一种人的战斗力
c[i]表示我方第二种人的战斗力
定义我方一组选手的战斗力为b[i]+c[j],第一种选手与第二种选手某种顺序两两组队后,与对方进行pk,共有$n!$种pk顺序,求最大期望×n
题解:
显然求我方b[i]+c[j]的方案,使得期望最大。
考虑两两组队会和对方n个队各pk一场,故贡献即为对方战斗力小于己方的价值
$n^{3}$预处理b[i]+c[j]的贡献,然后KM求最大带权匹配即可
写这个题的意义在于之前并不会$n^{3}$的KM,现场费用流各种优化tle,以及网上部分KM板子有问题,故留一下板子。
#include <bits/stdc++.h> using namespace std; #define LL long long #define ULL unsigned long long inline LL read(){ LL x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define INF 0x3f3f3f3f3f3f3f3f #define NPOS -1 #define MAXN 500 int n; LL g[MAXN][MAXN],hl[MAXN],hr[MAXN],slk[MAXN]; int fl[MAXN],fr[MAXN],pre[MAXN],vl[MAXN],vr[MAXN],q[MAXN],ql,qr; LL a[MAXN],b[MAXN],p[MAXN],c[MAXN]; inline int check(int i){ vl[i]=1; if (fl[i]!=NPOS){ q[qr++]=fl[i]; vr[fl[i]]=1; return 1; } while (i!=NPOS){ fl[i]=pre[i]; swap(i,fr[fl[i]]); } return 0; } void bfs(int s){ for (int i=1; i<=n; i++) vl[i]=vr[i]=0,slk[i]=INF; for (vr[q[ql = 0] = s] = qr = 1; ;){ for (LL d ; ql < qr; ){ for (int i=1,j=q[ql++]; i<=n; i++){ if (!vl[i] && slk[i] >= (d = hl[i]+hr[j] - g[i][j]) ){ pre[i]=j; if (d) slk[i]=d; else if (!check(i)) return; } } } LL d = INF; for (int i=1; i<=n; i++){ if (!vl[i] && d > slk[i]) d= slk[i]; } for (int i=1; i<=n; i++){ if (vl[i]) hl[i] +=d; else slk[i] -=d; if (vr[i]) hr[i] -=d; } for (int i=1; i<=n; i++) if (!vl[i] && !slk[i] && !check(i)) return; } } LL solve(){ for (int i=1; i<=n; i++) fl[i]=fr[i]=NPOS,hr[i]=0; for (int i=1; i<=n; i++) hl[i]=*max_element(g[i]+1,g[i]+n+1); for (int j=1; j<=n; j++) bfs(j); LL re = 0; for (int i=1; i<=n; i++) if (g[i][fl[i]]) re+=g[i][fl[i]]; else fl[i]=0; return re; } int main(){ n=read(); for (int i=1; i<=n; i++) a[i]=read(); for (int i=1; i<=n; i++) p[i]=read(); for (int i=1; i<=n; i++) b[i]=read(); for (int i=1; i<=n; i++) c[i]=read(); for (int i=1; i<=n; i++){ for (int j=1; j<=n; j++){ LL v = b[i]+c[j]; for (int k=1; k<=n; k++) if (a[k]<v) g[i][j]+=p[k]; } } LL ans = solve(); printf("%lld\n",ans); return 0; } /* 4 1 2 3 4 1 1 1 1 0 0 1 1 0 1 1 2 */
——It's a lonely path. Don't make it any lonelier than it has to be.