@ Noi.ac - 507 @ bipartite graph maximum weight matching


@description@

One day you learn a bipartite graph algorithm to solve the maximum weight matching algorithm you decided to apply to the NOI game.

Given a complete bipartite graph. In this figure, the size of the two parts are n. For point u and the point v of the first portion is a second portion connected to the right side thereof is \ (C_ {} UV UV + K_ {x} \) , where x is a variable value undefined.

You will be given multiple times to a value of x for each value of x, you need to answer half of the total weight of the complete graph corresponding to the maximum weight matching.

input
of the first row of a number n, is as defined the title.

Next n lines of n integers, wherein a first number of i-th row j to the value of cij.

Next nn lines of nn integers, wherein a first number of i-th row j to the value of kij.

Next, a number q, represents the number of a given value of x.

Next q lines of a given integer value of x.

output
output q lines, each of a number, which represents the i-th row corresponding to the i th answer value of x.

sample input
3
0 0 2
0 2 0
2 0 0
0 1 0
1 1 0
0 0 1
3
0
1
3
sample output
6
7
9

explanation
for x = 0, the maximum matching of 0 → 2,1 → 1,2 → 0, the answer is 2 + 2 + 2 = 6.

For x = 1, the maximum match is still 0 → 2,1 → 1,2 → 0, since only \ (k_ {11} = 1 \) and the other two sides of k is zero, and only the second side edge the right to change, 3. The answer is 2 + 3 + 2 = 7.

For x = 3, the maximum matching becomes 0 → 1,1 → 0,2 → 2, since the value of k 1 are the three sides, the right side are turned into 3. The answer is 3 + 3 + 3 = 9.

To 100% of the data, 1≤n≤50,1≤q≤100000,0≤cij≤10 ^ 7,0≤kij≤1, given the value of x is an integer between 0 and 10 ^ 7.

@solution@

The answer is not difficult to find some form as the form of K * x + C. Because most n edges match, the 1 <= K <= n.
Further found that, unique to each of a K C. This means that changes will only answer there are n possibilities.
We just need to find these n possibilities, and then look for a possibility which corresponds to the challenge for each inquiry.

Intuitively can be found (at the same time also be required to prove difficult to use), as x increases, the optimal solution corresponding constant K increases.
This means that each of the corresponding K x is always a contiguous range, so we can find each of the K interval corresponding to the value of two points by x.

When considering the use of solving the maximum weight matching algorithm KM O (n ^ 3) to solve, we pretreatment time complexity of O (n ^ 4 * log ( A)), where A = 10 ^ 7 is a constant.
And n need only to traverse interrogation possibilities, so the total query time complexity of O (nq).
As long as your writing is really KM algorithm is O (n ^ 3) (go uoj # 80 quiz) instead of O (n ^ 4) can live.

In fact, only really use the resulting x q times asked in x. We can ask the sort query bipartite, may be approaching the time complexity O (n ^ 4 * log (q))
But I'm too lazy to write this optimization.

@accepted code@

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int INF = 1<<30;
int c[50 + 5][50 + 5], k[50 + 5][50 + 5], K, X, C;
int f(int x, int y) {return k[x][y]*X + c[x][y];}
int lx[50 + 5], ly[50 + 5], lk[50 + 5], slk[50 + 5];
bool vx[50 + 5], vy[50 + 5];
int n, q;
bool dfs(int x) {
    vx[x] = true;
    for(int y=1;y<=n;y++) {
        if( vy[y] ) continue;
        int t = lx[x] + ly[y] - f(x, y);
        if( t == 0 ) {
            vy[y] = true;
            if( (!lk[y]) || dfs(lk[y]) ) {
                lk[y] = x;
                return true;
            }
        }
        else slk[y] = min(slk[y], t);
    }
    return false;
}
void KM(int p) {
    X = p;
    for(int i=1;i<=n;i++) {
        lx[i] = ly[i] = lk[i] = 0;
        for(int j=1;j<=n;j++)
            lx[i] = max(lx[i], f(i, j));
    }
    for(int x=1;x<=n;x++) {
        for(int i=1;i<=n;i++)
            vx[i] = vy[i] = false, slk[i] = INF;
        if( !dfs(x) ) {
            while( true ) {
                int del = INF, y = 0;
                for(int i=1;i<=n;i++)
                    if( !vy[i] ) del = min(del, slk[i]);
                for(int i=1;i<=n;i++) {
                    if( vx[i] ) lx[i] -= del;
                    if( vy[i] ) ly[i] += del;
                }
                for(int i=1;i<=n;i++)
                    if( !vy[i] ) {
                        slk[i] -= del;
                        if( slk[i] == 0 )
                            y = i;
                    }
                if( !lk[y] ) break;
                vx[lk[y]] = vy[y] = true;
                for(int i=1;i<=n;i++)
                    slk[i] = min(slk[i], lx[lk[y]] + ly[i] - f(lk[y], i));
            }
            for(int i=1;i<=n;i++)
                vx[i] = vy[i] = false;
            dfs(x);
        }
    }
    K = C = 0;
    for(int i=1;i<=n;i++)
        K += k[lk[i]][i], C += c[lk[i]][i];
}
struct node{
    int k, c, l, r;
    node(int _k=0, int _c=0, int _l=0, int _r=0):k(_k), c(_c), l(_l), r(_r){}
};
vector<node>vec;
int pk, pc;
int solve(int l, int r) {
    while( l < r ) {
        int mid = (l + r + 1) >> 1; KM(mid);
        if( pk == K ) l = mid;
        else r = mid - 1;
    }
    return l;
}
int main() {
    scanf("%d", &n);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            scanf("%d", &c[i][j]);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            scanf("%d", &k[i][j]);
    int le = 0, ri = int(1E7);
    while( le <= ri ) {
        KM(le); pk = K, pc = C;
        int res = solve(le, ri);
        vec.push_back(node(pk, pc, le, res));
        le = res + 1;
    }
    scanf("%d", &q);
    for(int i=1;i<=q;i++) {
        int x; scanf("%d", &x);
        for(int j=0;j<vec.size();j++)
            if( vec[j].l <= x && x <= vec[j].r )
                printf("%d\n", vec[j].k*x + vec[j].c);
    }
}

@details@

This question in itself is not difficult, just need to think of the beginning of K * x + C in K values ​​of n only.

In addition most out of online KM algorithm Baidu are false O (n ^ 3) (including Baidu Encyclopedia), if you really want to find O (n ^ 3) code search solution to a problem can go 80 uoj #.
In fact, I do not know the KM algorithm can flow through into costs. While the complexity of the cost flow is O (metaphysics), but the complete graph should run faster. . .

Guess you like

Origin www.cnblogs.com/Tiw-Air-OAO/p/11112549.html