[POJ 2516]Minimum Cost[费用流][建图]
来源:互联网 发布:sql注入语句 编辑:程序博客网 时间:2024/04/28 19:05
题目链接:[POJ 2516]Minimum Cost[费用流][建图]
题意分析:
N个店主,M个供货商,K种货物,每个店主都有自己需要的货物数量,每个供货商都会提供一定数量的货物,每个供货商给店主提供不同货物的单位价格不同,现在问题来了:供货商如何花费最少的费用给店主提供上货物呢?最少费用是多少?无法满足要求则输出-1。
解题思路:
这题如果将店主的需要货物拆点,供货商的提供货物拆点,再来个超级源汇点,边的个数多的吓人。。。。。
发现可以一种货物计算一次费用,返回的最大流就是这种货物能够提供的最大总数,如果这个最大流<店主需要的量,那么就是-1了。
于是我们一种货物建一次图,源点到供货商连一条边,容量为供货量,费用为0,汇点和店主连一条边,容量为需求量,费用为0,供货商和店主连边,容量为INF,费用为当前矩阵对应的费用。此题得解。
个人感受:
个人思路一直是第一行的解题思路。。。。。各种拆点。。。。。这回知道连图都能拆了。。。。
具体代码如下:
#include<algorithm>#include<cctype>#include<cmath>#include<cstdio>#include<cstring>#include<iomanip>#include<iostream>#include<map>#include<queue>#include<set>#include<sstream>#include<stack>#include<string>#define ll long long#define pr(x) cout << #x << " = " << (x) << '\n';using namespace std;const int MAXN = 200;const int MAXM = 2e4;const int INF = 0x3f3f3f3f;struct Edge{ int to,next,cap,flow,cost;}edge[MAXM];int head[MAXN], tol, nk[60][60], mk[60][60], need[60], have[60];int pre[MAXN],dis[MAXN];bool vis[MAXN];int N;//节点总个数,节点编号从0~N-1void init(int n){ N = n; tol = 0; memset(need, 0, sizeof need); memset(have, 0, sizeof have);}void addedge(int u,int v,int cap,int cost){ edge[tol].to = v; edge[tol].cap = cap; edge[tol].cost = cost; edge[tol].flow = 0; edge[tol].next = head[u]; head[u] = tol++; edge[tol].to = u; edge[tol].cap = 0; edge[tol].cost = -cost; edge[tol].flow = 0; edge[tol].next = head[v]; head[v] = tol++;}bool spfa(int s,int t){ queue<int>q; for(int i = 0;i < N;i++) { dis[i] = INF; vis[i] = false; pre[i] = -1; } dis[s] = 0; vis[s] = true; q.push(s); while(!q.empty()) { int u = q.front(); q.pop(); vis[u] = false; for(int i = head[u]; i != -1;i = edge[i].next) { int v = edge[i].to; if(edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost ) { dis[v] = dis[u] + edge[i].cost; pre[v] = i; if(!vis[v]) { vis[v] = true; q.push(v); } } } } if(pre[t] == -1)return false; else return true;}//返回的是最大流, cost存的是最小费用int minCostMaxflow(int s,int t,int &cost){ int flow = 0; while(spfa(s,t)) { int Min = INF; for(int i = pre[t];i != -1;i = pre[edge[i^1].to]) { if(Min > edge[i].cap - edge[i].flow) Min = edge[i].cap - edge[i].flow; } for(int i = pre[t];i != -1;i = pre[edge[i^1].to]) { edge[i].flow += Min; edge[i^1].flow -= Min; cost += edge[i].cost * Min; } flow += Min; } return flow;}int main(){ int n, m, k; while (~scanf("%d%d%d", &n, &m, &k) && (n|m|k)) { init(n + m + 2); int s = 0, t = n + m + 1; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= k; ++j) scanf("%d", &nk[i][j]), need[j] += nk[i][j]; } for (int i = 1; i <= m; ++i) { for (int j = 1; j <= k; ++j) scanf("%d", &mk[i][j]), have[j] += mk[i][j]; } bool flag = 0; int x = 0, ans = 0; for (int l = 1; l <= k; ++l) { tol = 0; memset(head, -1, sizeof head); for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { scanf("%d", &x); addedge(n + j, i, mk[j][l], x); } } for (int i = 1; i <= n; ++i) addedge(i, t, nk[i][l], 0); for (int i = 1; i <= m; ++i) addedge(s, i + n, mk[i][l], 0); int flow = minCostMaxflow(s, t, ans); if (flow < need[l]) flag = 1; } if (flag) printf("-1\n"); else printf("%d\n", ans); } return 0;}
0 0
- [POJ 2516]Minimum Cost[费用流][建图]
- POJ 2516 Minimum Cost(费用流 建图)
- POJ 2516 Minimum Cost //费用流
- POJ 2516 Minimum Cost 费用流
- 【POJ】 2516 Minimum Cost 费用流
- POJ 2516 Minimum Cost | 费用流
- POJ 2516 Minimum Cost(费用流)
- poj 2516 Minimum Cost (最小费用流)
- POJ 2516 Minimum Cost(费用流)
- POJ 2516 — Minimum Cost 费用流
- poj 2516 Minimum Cost (费用流)
- poj 2516 Minimum Cost 最小费用流
- Poj 2516 Minimum Cost【费用流Min_Cost_Max_flow】
- POJ 2516 Minimum Cost (费用流)
- POJ 2516 Minimum Cost(网络流之费用流)
- 【网络流】【费用流】[POJ 2516]Minimum Cost
- POJ 2516 Minimum Cost 【MCMF:最小费用最大流】
- POJ 2516 Minimum Cost 最小费用最大流
- android 9png的效果a
- Android APK系列6-------APK反编译
- 算法八皇后问题
- VirtualBox双机调试
- iOS开发中WebView的使用
- [POJ 2516]Minimum Cost[费用流][建图]
- jquery ajax级联二级下拉,jquey select级联
- POJ 1035 Spell checker(字符串比较)
- 「C++ Primer」3.22 迭代器未定义操作导致段错误问题
- mysql5.6配置版
- TCP的三次握手(建立连接)和四次挥手(关闭连接)
- Eclipse各种快捷键方式
- JVM
- Linux---centos编译安装ffmpeg