南京现场赛J题Spy【KM算法模板题】

Over time, those coaches in BDN Collegiate Progranuning Contest split into two camps.The big danger is that, while optimists and pessimists battle it out, the environment of this area becomes ever more divided between universities with outstanding student resources surrounded by a vast neglected group of stagnation.

Amy and Bob, as the linchpins of these two camps respectively, decided to put the end to the rival. Now both camps hold nn coders and nn tea-bringers as the last resource on hand. They will form teams in pair that each team should consist of a coder and a tea-bringer. The power of a team is regarded as the sum of powers of both members.

Now Bob hired a spy and has got some information about the plan of his rival: the power of each team which will present for the enemy camp, and the corresponding unit of reputations that Bob would gain after beating this team. Naturally, he hopes to make the best arrangement of teams in his camp for more reputations.

These two camps will have a collision soon, and their teams will fight one on one in random order. That is, we may have n!n! different situations appearing in this collision. A team would triumphantly return if it has a higher power. When two teams of the same power meet, the one led by Amy would beat the rival by a neck.

Can you calculate the maximum expected unit of reputations that Bob will gain? To make the answer be an integer, you are asked to multiply the answer by nn and we guarantee that the expected number multiplied by nn should always be an integer.

Input
The input contains five lines, and the first line is consist of an integer n n n(1 ≤ \leq n n n ≤ \leq 400).
The second line contains n n n integers a 1 a_1 a1, a 2 a_2 a2,—, a n a_n an, with − 1 0 18 -10^{18} 1018 ≤ \leq a i a_i ai ≤ \leq 1 0 18 10^{18} 1018, indicating the powers of all the teams led by Amy.
The third line contains n n n integers p 1 p_1 p1, p 2 p_2 p2,—, p n p_n pn, with 1 ≤ \leq p i p_i pi ≤ \leq 10000, indicating the corresponding units of reputations that Bob would gain if these teams led by Amy are beaten.
The fourth line contains n n n integers b 1 b_1 b1, b 2 b_2 b2,—, b n b_n bn, with − 1 0 18 -10^{18} 1018 ≤ \leq b i b_i bi ≤ \leq 1 0 18 10^{18} 1018, indicating the powers of all coders in the camp of Bob.
The last line contains n n n integers c 1 c_1 c1, c 2 c_2 c2,—, c n c_n cn, with − 1 0 18 -10^{18} 1018 ≤ \leq c i c_i ci ≤ \leq 1 0 18 10^{18} 1018, indicating the powers of all tea-bringers in the camp of Bob.
Output
Output an integer in a single line indicating the maximum expected number of wins multiplied by n n n.
样例输入
4
1 2 3 4
1 1 1 1
0 0 1 1
0 1 1 2
样例输出
3

这道题需要真正的 O ( n 3 ) O(n^3) O(n3)的板子才能过,也告诉我我之前的 O ( n 3 ) O(n^3) O(n3)的板子是错误的。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>

#define ll long long
#define len 500
#define INF 0x3f3f3f3f

using namespace std;

ll a[len], b[len], c[len], d[len];
bool vis[len], vis_y[len];
ll mmap[len][len];
ll slack[len], l[len];
ll wx[len], wy[len], pre[len];
int n;

void Init(){
    memset(a, 0, sizeof (a));
    memset(b, 0, sizeof (b));
    memset(c, 0, sizeof (c));
    memset(d, 0, sizeof (d));
    memset(vis, false, sizeof (vis));
    memset(mmap, 0, sizeof (mmap));
    memset(slack, 0, sizeof (slack));
    memset(wx, 0, sizeof (wx));
    memset(wy, 0, sizeof (wy));
    memset(l, 0, sizeof (l));
}

void bfs(int k)
{
    int px,py=0,yy=0,d;
    memset(pre,0,sizeof (pre));
    memset(slack,INF,sizeof (slack));
    l[py]=k;

    do
    {
        px=l[py],d=INF,vis[py]=true;
        for(int i=1;i<=n;i++)
            if(!vis[i])
            {
                if(slack[i]>wx[px]+wy[i]-mmap[px][i])
                    slack[i]=wx[px]+wy[i]-mmap[px][i],pre[i]=py;
                if(slack[i]<d) d=slack[i],yy=i;
            }
        for(int i=0;i<=n;i++)
            if(vis[i]) wx[l[i]]-=d,wy[i]+=d;
            else slack[i]-=d;
        py=yy;
    }while(l[py]!=0);
    while(py) l[py]=l[pre[py]],py=pre[py];
}
ll km()
{
    memset(wx,0,sizeof (wx));
    memset(wy,0,sizeof (wy));
    memset(l,0,sizeof (l));
    for(int i=1;i<=n;i++)
        memset(vis,0,sizeof (vis)),bfs(i);

    ll ans = 0;
    for (int i=1; i<=n; i++) ans += mmap[l[i]][i];
    return ans;
}

int main(){
    Init();
    scanf("%d", &n);
    for (int i=1; i<=n; i++) scanf("%lld", &a[i]);
    for (int i=1; i<=n; i++) scanf("%lld", &b[i]);
    for (int i=1; i<=n; i++) scanf("%lld", &c[i]);
    for (int i=1; i<=n; i++) scanf("%lld", &d[i]);

    for (int i=1; i<=n; i++){
        for (int j=1; j<=n; j++){
            for (int k=1; k<=n; k++){
                if (c[i] + d[j] > a[k]) mmap[i][j] += b[k];
            }
        }
    }

//    for (int i=1; i<=n; i++){
//        for (int j=1; j<=n; j++){
//            printf("%d ", mmap[i][j]);
//        }
//        printf("\n");
//    }
    ll ans = km();
    printf("%lld\n", ans);
    return 0;
}