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