题目描述
已知每个人做每件工作的收益Wij求一种分配的方案(每个人必须有工作),且收益最大。
输入描述
第一行一个整数N(1≤N≤300),下面是一个N∗N的矩阵,第i行第
输出描述
一个整数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;
}*/ 去掉注释就可以输出各种匹配
}

本文探讨了一种求解每个人做每件工作收益最大化的分配问题。通过输入描述、输出描述以及样例展示,解释了如何将问题转化为图论中的最小费用最大流问题,并提供了暴力求解与图论方法的思路对比。
2314

被折叠的 条评论
为什么被折叠?



