收益最大

题目描述

已知每个人做每件工作的收益Wij求一种分配的方案(每个人必须有工作),且收益最大。

输入描述

第一行一个整数N(1N300),下面是一个NN的矩阵,第i行第j个数Wij,(1Wij1000000),表示第i个人做第j件工作的收益。

输出描述

一个整数M,表示最大的收益。

样例输入

10
90 91 66 76 56 57 50 52 81 78 
50 82 61 91 64 98 83 73 97 87 
57 82 84 51 70 71 71 69 82 54 
88 77 65 85 62 82 89 73 99 61 
55 61 90 75 85 50 70 62 86 93 
99 68 74 75 99 99 93 59 96 74 
73 71 85 90 57 69 57 71 97 79 
81 93 98 72 92 56 50 58 67 60 
83 55 58 92 86 60 70 53 53 87 
62 87 55 94 78 66 98 59 58 64 

样例输出

923

思路1:暴力
思路2:把关系转换成图,跑最小费用最大流。

#include <cstdio>
#include <deque>
const int INF = 1000000007;
int c[1000][1000], m[1000][1000]; //cost_man_job
int n, s, t;
int SPFA(int s, int t)
{
    int dis[1000], f[1000];
    bool vis[1000];
    std::deque<int> q;
    for(int i = 0; i <= t; ++i)
    {
        dis[i] = INF;
        f[i] = i;
    }
    dis[s] = 0;
    vis[s] = true;
    q.push_back(s);
    int now, fnow;
    while(!q.empty())
    {
        now = q.front();
        q.pop_front();
        vis[now] = false;
        for(int i = s; i <= t; ++i)
            if(m[now][i])
                if(dis[i] > dis[now] + c[now][i])
                {
                    dis[i] = dis[now] + c[now][i];
                    f[i] = now;
                    if(!vis[i])
                    {
                        vis[i] = true;
                        q.push_back(i);
                    }
                }
    }
    now = t;
    int fl = 0;
    while(now != f[now])
    {
        fnow = f[now];
        fl += c[fnow][now];
        m[fnow][now] = 0;
        m[now][fnow] = 1;
        now = fnow;
    }
    return fl;
}
int zxfyzdl(int s, int t)
{
    int tmp, ans = 0;
    while(tmp = SPFA(s, t))
        ans += tmp;
    return ans;
}
int main()
{
    scanf("%d", &n);
    s = 0; t = n + n + 1;
    for (int i = 1; i <= n; ++i)
    {
        c[s][i] = 0;
        c[i][s] = 0;
        m[s][i] = 1;
        for (int j = 1; j <= n; ++j)
        {
            m[i][j+n] = 1;
            scanf("%d", &c[i][j+n]);
            c[j+n][i]  = c[i][j+n];
            c[i][j+n] = -c[i][j+n];
        }
        c[i+n][t] = 0;
        c[t][i+n] = 0;
        m[i+n][t] = 1;
    }
    printf("%d\n", -zxfyzdl(s, t));
    /*for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= n; ++j)
            if(m[j + n][i])
            {
                printf("%d %d\n", i, j);
                break;
            }*/  去掉注释就可以输出各种匹配
}

posted on 2015-08-27 10:40  MagHSK  阅读(172)  评论(0编辑  收藏  举报