POJ 3686 The Windy's(最小费用最大流)
来源:互联网 发布:金牌淘宝客服 编辑:程序博客网 时间:2024/06/03 15:23
点击打开链接
这是挑战上的一道题,不得不说十分的难懂。我看了好久才明白什么意思,当然好像跟挑战上的意思有点区别但是能A就行。
首先,我们知道,这些玩具是可以交给各个工厂去加工的,一个工厂可以加工多个工厂,这里还没什么头绪。
我们来看只有一个工厂的时候,加工n个玩具的总时间就会有T = Z1 + (Z1 + Z2) + .... + (Z1 + Z2 + .... + Zn)
也就是T = n * Z1 + (n - 1) * Z2 + ..... + 1 * Zn
我们可以从上式中看出一些东西,就是玩具i,假设他是在这个工厂里面第k个加工的,那么他就是上面的Zk
我们可以看到,Zk对总时间的贡献就是(n - k + 1) * Zk。
这时候我们就可以把每个工厂给拆点了,拆成了n个点,第k个点代表的是第k个加工。
我们要的是总共的时间最小,那么构图:
一个超级源点连向每个玩具,流量为1,花费为0.
每个工厂拆出来的点连向超级汇点,流量为1,花费为0.
每个玩具i和每个工厂j的第k个加工的点连一条流量为1,花费为(n-k+1)*G[i][j]的边,G[i][j]就是玩具i在j工厂加工的费用。
然后就跑一跑费用流输出即可。
代码如下:
#include<iostream>#include<cstdio>#include<vector>#include<queue>#include<utility>#include<stack>#include<algorithm>#include<cstring>#include<string>#include<cmath>using namespace std;const int INF = 0x3f3f3f3f;const int maxn = 2600;const int maxm = 260000;int n, m;int head[maxn], to[maxm], front[maxm], flow[maxm], cost[maxm], ppp;int dis[maxn], minflow[maxn];bool flag[maxn];pair<int, int> par[maxn];int G[55][55];struct MIN_COST_MAX_FLOW{void init() {memset(head, -1, sizeof(head));ppp = 0;}bool spfa(int s, int e){int u, v;for(int i = 0; i <= e; i++)dis[i] = INF;memset(flag, 0, sizeof(flag));dis[s] = 0;minflow[s] = INF;queue <int> q;q.push(s);while(!q.empty()){u = q.front();q.pop();flag[u] = 0;for(int i = head[u]; ~i; i = front[i]){v = to[i];if(flow[i] && dis[v] > dis[u] + cost[i]){dis[v] = dis[u] + cost[i];par[v] = (make_pair(u, i));minflow[v] = min(minflow[u], flow[i]);if(!flag[v]){flag[v] = 1;q.push(v);}}}}if(dis[e] == INF)return 0;return 1;}int slove(int s, int e){int ans = 0, p;while(spfa(s, e)){p = e;while(p != s){flow[par[p].second] -= minflow[e];flow[par[p].second^1] += minflow[e];p = par[p].first;}ans += dis[e];}return ans;}void add_edge(int u, int v, int f, int c){to[ppp] = v, front[ppp] = head[u], flow[ppp] = f, cost[ppp] = c, head[u] = ppp++;to[ppp] = u, front[ppp] = head[v], flow[ppp] = 0, cost[ppp] = -c, head[v] = ppp++;}}mcmf;int main(){//freopen("poj_in.txt", "r", stdin);int T;cin >> T;while(T--) {mcmf.init();scanf("%d%d", &n, &m);for(int i = 0; i < n; i++) {for(int j = 0; j < m; j++) {scanf("%d", &G[i][j]);}}int s = n + m * n + 1, t = s + 1;for(int i = 0; i < n; i++) {mcmf.add_edge(s, i, 1, 0);}for(int j = 0; j < m; j++) {for(int k = 0; k < n; k++) {mcmf.add_edge(n + j * n + k, t, 1, 0);for(int i = 0; i < n; i++) {mcmf.add_edge(i, n + j * n + k, 1, (n - k) * G[i][j]);}}}int ans = mcmf.slove(s, t);printf("%.6f\n", (double)(ans) / n);}return 0;}
阅读全文
0 0
- poj 3686 The Windy's(最小费用最大流)
- POJ 3686 The Windy's(最小费用最大流)
- The Windy's (poj 3686 最小费用最大流 建图经典)
- POJ--3686[The Windy's] 最小费用流或KM
- 【POJ 3686 The Windy's】+ 最小费用流
- poj 3686 The Windy\'s 最小费用流 建图 16_05_14
- POJ-3686-The Windy's(KM/费用流)
- 【POJ 3686】【最小费用最大流或者KM算法 指派问题变形(需要拆点)】The Windy's n个玩具指派给m个工厂生产
- POJ_3686_The Windy's(最小费用流 / KM)
- poj 3686 The Windy's(最小权值和)
- POJ 3686 The Windy's 最小权值匹配
- poj 3686 The Windy's
- poj 3686 The Windy's
- POJ 3686 The Windy's
- poj 3686 The Windy's
- POJ 3686 The Windy's
- POJ-3686-The Windy's
- poj 3686 The Windy's
- 设计模式六大原则
- : Android之linux基础教学之三 分页机制
- 字符排序 java HashSet去重与遍历的三种方法
- 静态联编和动态联编
- Andorid的Linux基础教学之四 进程的生死存亡
- POJ 3686 The Windy's(最小费用最大流)
- EL自定义简单函数实例
- : Andorid的Linux基础教学之五 中断机制
- 软件开发模型
- 关于Android沉浸式状态栏的解决方法之一(伪沉浸式)
- 使用git pull文件时和本地文件冲突怎么办?
- Android之linux基础教学之六 异常
- Kotlin Reference (九) Properties and Fields
- 把idea的项目上传的gitlab上