gggyt  
没谁离不开谁
/*  gyt
       Live up to every day            */
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<cstring>
#include<queue>
#include<set>
#include<string>
#include<map>
#include <time.h>
#define PI acos(-1)
using namespace std;
typedef long long ll;
typedef double db;
const int maxn = 400;
const ll maxm = 1e7;
const int mod = 1e9+7;
const int INF = 0x3f3f3f;
const ll inf = 1e14 + 5;
const db eps = 1e-9;
const ll Max=1e19;
int mapp[maxn][maxn], visx[maxn], visy[maxn];
int lx[maxn], ly[maxn];
int match[maxn];
int n;

int hungry(int u) {
    visx[u] = true;
    for(int i = 0; i < n; ++i)
    {
        if(!visy[i] && lx[u] + ly[i] == mapp[u][i])
        {
            visy[i] = true;
            if(match[i] == -1 || hungry(match[i]))
            {
                match[i] = u;
                return true;
            }
        }
    }
    return false;
}
void KM() {
    int temp;
    memset(lx, 0, sizeof(lx)); //初始化顶标
    memset(ly, 0, sizeof(ly)); //ly[i]为0
    for(int i = 0; i < n; ++i) //lx[i]为权值最大的边
        for(int j = 0; j < n; ++j)
            lx[i] = max(lx[i], mapp[i][j]);
    for(int i = 0; i < n; ++i) //对n个点匹配
    {
        while(1)
        {
            memset(visx, false, sizeof(visx));
            memset(visy, false, sizeof(visy));
            if(hungry(i)) //匹配成功
                break;
            else //匹配失败,找最小值
            {
                temp = INF;
                for(int j = 0; j < n; ++j) //x在交错树中
                    if(visx[j])
                        for(int k = 0; k < n; ++k) //y在交错树外
                            if(!visy[k] && temp > lx[j] + ly[k] - mapp[j][k])
                                temp = lx[j] + ly[k] - mapp[j][k];
                for(int j = 0; j < n; ++j) //更新顶标
                {
                    if(visx[j])
                        lx[j] -= temp;
                    if(visy[j])
                        ly[j] += temp;
                }
            }
        }
    }
}
void solve() {
     int ans;
    while(scanf("%d", &n) != EOF)
    {
        ans = 0;
        memset(match, -1, sizeof(match));
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                scanf("%d", &mapp[i][j]);
        KM();
        for(int i = 0; i < n; i++) //权值相加
            ans += mapp[match[i]][i];
        printf("%d\n", ans);
    }
}
int main() {
    int t=1;
    //freopen("in.txt", "r", stdin);
    //scanf("%d", &t);

    while(t--)
        solve();
}

 

posted on 2017-07-31 16:21  gggyt  阅读(249)  评论(0编辑  收藏  举报