题目链接:
http://poj.org/problem?id=2516
分析:
给出N个商店,M个厂家,K种货物,然后给出N个商店对于K种货物的需求量,和M个厂家对于K种货物的供给量,最后给出没种货物的每一份分别从N个商店运输到M个厂家的花费。求能不能满足着N个商店的需求,若能够输出最小花费,若不能,输出-1/。
一看便是一道网络流的题,辛苦建完边后发现超时了,结果是因为邻接矩阵查询超时的,这里注意一下:
邻接矩阵法由于没有相连的边也占有空间,因此存在浪费空间的问题,而临街链表法合理利用存储空间;
邻接链表法比较耗时,牺牲很大的时间来查找,因此比较耗时,而邻接矩阵法相比邻接链表法来说,时间复杂度低;
总结,邻接矩阵法:用时间换空间;邻接链表法:用空间换时间。
memset(capacity, 0, sizeof(capacity));
memset(flow, 0, sizeof(flow));
memset(weight, 0, sizeof(weight));
for (j = 1; j <= m; j++)
{
capacity[0][j] = capacity_have[j][i]; //S 到N个K
}
for (j = 1; j <= n; j++)
{
capacity[m + j][m + n + 1] = capacity_need[j][i];//M个K到T
}
for (j = 1; j <= m; j++)
{
for (d = 1; d <= n; d++)
{
capacity[j][d + m] = capacity_have[j][i];//N个K到M个K
}
}
for (j = 1; j <= m; j++)
{
for (d = 1; d <= n; d++)
{
weight[j][d + m] = construction_cost[i][j][d]; //记录N到M的花费
weight[d + m][j] = -construction_cost[i][j][d]; //反向花费为负数,便于退流
}
}
2.SPFA(邻接矩阵版本)
int shortestdistances[M];
int pre_node[M];
bool visited[M];
bool spfa()
{
for (int i = 0; i <= n + m + 1; i++)
{
shortestdistances[i] = inf;
pre_node[i] = -1;
visited[i] = false;
}
shortestdistances[0] = 0;
visited[0] = true;
queue <int> q;
q.push(0);
while (!q.empty())
{
int t = q.front();
q.pop();
visited[t] = false;
for (int i = 1; i <= n + m + 1; i++)
{
if (capacity[t][i] > flow[t][i] && shortestdistances[i] > shortestdistances[t] + weight[t][i])
{
shortestdistances[i] = shortestdistances[t] + weight[t][i];
pre_node[i] = t;
if (!visited[i])
{
q.push(i);
visited[i] = true;
}
}
}
}
if (pre_node[n + m + 1] == -1)
{
return false;
}
return true;
}
3.计算出最校费用
int capacity[M][M]; //邻接矩阵
int flow[M][M]; //流量
void getMaxflow()
{
while (spfa())
{
int maxflow = inf;
int p = n + m + 1;
while (pre_node[p] != -1)
{
maxflow = min(maxflow, capacity[pre_node[p]][p] - flow[pre_node[p]][p]);
p = pre_node[p];
}
p = n + m + 1;
while (pre_node[p] != -1)
{
flow[pre_node[p]][p] += maxflow;
flow[p][pre_node[p]] = -flow[pre_node[p]][p];
p = pre_node[p];
}
}
}
#include
#include
#include
using namespace std;
#define M 105
#define inf 1 << 30
int capacity_need[M][M];//N个商家的需求
int capacity_have[M][M];//M个厂家的供给
int construction_cost[M][M][M]; //每个物品的具体花费
int n, m, k;
int capacity[M][M]; //邻接矩阵
int flow[M][M]; //流量
int weight[M][M]; //从N到M的花费
int shortestdistances[M];//最短路
int pre_node[M];
bool visited[M];
bool spfa()
{
for (int i = 0; i <= n + m + 1; i++)
{
shortestdistances[i] = inf;
pre_node[i] = -1;
visited[i] = false;
}
shortestdistances[0] = 0;
visited[0] = true;
queue <int> q;
q.push(0);
while (!q.empty())
{
int t = q.front();
q.pop();
visited[t] = false;
for (int i = 1; i <= n + m + 1; i++)
{
if (capacity[t][i] > flow[t][i] && shortestdistances[i] > shortestdistances[t] + weight[t][i])
{
shortestdistances[i] = shortestdistances[t] + weight[t][i];
pre_node[i] = t;
if (!visited[i])
{
q.push(i);
visited[i] = true;
}
}
}
}
if (pre_node[n + m + 1] == -1)
{
return false;
}
return true;
}
void getMaxflow()
{
while (spfa())
{
int maxflow = inf;
int p = n + m + 1;
while (pre_node[p] != -1)
{
maxflow = min(maxflow, capacity[pre_node[p]][p] - flow[pre_node[p]][p]);
p = pre_node[p];
}
p = n + m + 1;
while (pre_node[p] != -1)
{
flow[pre_node[p]][p] += maxflow;
flow[p][pre_node[p]] = -flow[pre_node[p]][p];
p = pre_node[p];
}
}
}
int main()
{
int i, j, d, ans;
while (cin >> n >> m >> k, n || m || k)
{
ans = 0;
bool flag = false;
for (i = 1; i <= n; i++)
{
for (j = 1; j <= k; j++)
{
cin >> capacity_need[i][j];
}
}
for (i = 1; i <= m; i++)
{
for (j = 1; j <= k; j++)
{
cin >> capacity_have[i][j];
}
}
for (i = 1; i <= k; i++)
{
for (j = 1; j <= n; j++)
{
for (d = 1; d <= m; d++)
{
cin >> construction_cost[i][d][j];
}
}
}
for (i = 1; i <= k; i++)
{
memset(capacity, 0, sizeof(capacity));
memset(flow, 0, sizeof(flow));
memset(weight, 0, sizeof(weight));
for (j = 1; j <= m; j++)
{
capacity[0][j] = capacity_have[j][i];
}
for (j = 1; j <= n; j++)
{
capacity[m + j][m + n + 1] = capacity_need[j][i];
}
for (j = 1; j <= m; j++)
{
for (d = 1; d <= n; d++)
{
capacity[j][d + m] = capacity_have[j][i];
}
}
for (j = 1; j <= m; j++)
{
for (d = 1; d <= n; d++)
{
weight[j][d + m] = construction_cost[i][j][d];
weight[d + m][j] = -construction_cost[i][j][d];
}
}
getMaxflow();
for (j = 1; j <= n; j++) //查询是否满足每个店家的需求
{
if (capacity[j + m][n + m + 1] != flow[j + m][n + m + 1])
{
flag = true;
break;
}
}
if (flag)
{
break;
}
for (j = 1; j <= m; j++)
{
for (d = 1; d <= n; d++)
{
ans += flow[j][d + m] * weight[j][d + m];
}
}
}
if (flag)
{
cout << -1 << endl;
}
else
{
cout << ans << endl;
}
}
}