Cod sursa(job #2333754)

Utilizator akaprosAna Kapros akapros Data 1 februarie 2019 21:55:08
Problema Cc Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.78 kb
#include <bits/stdc++.h>
#define maxN 302
#define inf 0x3fffffff
using namespace std;

FILE *fin = freopen("cc.in", "r", stdin);
FILE *fout = freopen("cc.out", "w", stdout);

int N;
int c[maxN][maxN], cost[maxN][maxN];

int Pair[maxN];
bool vis[maxN], mvc[maxN];

int ans;

bool Pairup(int x)
{
    if (vis[x])
        return 0;
    vis[x] = 1;
    for (int y = 0; y < N; ++ y)
        if (c[x][y] == 0)
            if (Pair[y + N] == -1 || Pairup(Pair[y + N]))
            {
                Pair[x] = y + N;
                Pair[y + N] = x;
                return 1;
            }
    return 0;
}
int maxMatching()
{
    bool ok = false;
    ans = 0;
    memset(Pair, -1, sizeof(Pair));
    do
    {
        ok = false;
        memset(vis, 0, sizeof(vis));
        for (int i = 0; i < N; ++ i)
            if (Pair[i] == -1)
                ok |= Pairup(i);
    }
    while (ok);
    int ret = 0;
    for (int i = 0; i < N; ++ i) if (Pair[i] != -1)
        {
            ans += cost[i][Pair[i] - N];
            ++ ret;
        }
    return ret;
}
/// try to use thins approach for normal graphs?
void comp0WeightEdges()
{
    for (int i = 0; i < N; ++ i)
    {
        int minc = inf;
        for (int j = 0; j < N; ++ j)
            minc = min(minc, c[i][j]);
        for (int j = 0; j < N; ++ j)
            c[i][j] -= minc;
        //ans += minc;
    }
}
void compMVC(int u)
{
    for (int v = 0; v < N; ++ v)
        if (c[u][v] == 0 && !mvc[v + N])
        {
            mvc[v + N] = true;
            mvc[Pair[v + N]] = false;
            compMVC(Pair[v + N]);
        }
}
int minEdgeMVC()
{
    int delta = inf;
    for (int i = 0; i < N; ++ i)
        if (!mvc[i])
            for (int j = 0; j < N; ++ j) if (!mvc[j + N])
                    delta = min(delta, c[i][j]);
    return delta;
}
void recompC(int delta)
{
    for (int i = 0; i < N; ++ i)
        for (int j = 0; j < N; ++ j)
            if (!mvc[i] && !mvc[j + N])
                c[i][j] -= delta;
            else if (mvc[i] && mvc[j + N])
                c[i][j] += delta;
}

int main()
{
    scanf("%d", &N);
    for (int i = 0; i < N; ++ i)
        for (int j = 0; j < N; ++ j)
        {
            scanf("%d", &c[i][j]);
            cost[i][j] = c[i][j];
        }

    comp0WeightEdges();
    int prvD = 0;
    while(1)
    {
        int sz = maxMatching();
        if (sz == N)
            break;
        memset(mvc, false, sizeof(mvc));
        for (int i = 0; i < N; ++ i)
            if (Pair[i] != -1)
                mvc[i] = true;
        for (int i = 0; i < N; ++ i)
            if (Pair[i] == -1)
                compMVC(i);
        int delta = minEdgeMVC();

        recompC(delta);
    }

    printf("%d\n", ans);
    return 0;
}