博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
poj_3436 网络最大流
阅读量:7028 次
发布时间:2019-06-28

本文共 5134 字,大约阅读时间需要 17 分钟。

题目大意

    生产电脑的工厂将一台电脑分成P个部件来进行流水线生产组装,有N个生产车间,每个车间可以将一个半成品电脑添加某些部件,使之成为另一个半成品电脑或者成为一台完好的电脑,且每个车间有一个效率,即在单位时间内可以将K个半成品组装为另外K个半成品或者完好的电脑。每个车间在组装完成之后,都将组装后的半成品送到另外一个车间,成品直接送到成品区。 

    现在给出这N个车间的组装原部件集合以及组装后的部件集合(其中 in[1,2,3...p]中 in[i]表示第i种组装元部件,out[1,2,3...p]中out[i]表示第i种组装后的部件。且in[i] = 0表示元部件集合中必须没有第i种部件,in[i]=1表示元部件集合中必须有第i种部件,in[i] = 2表示元部件集合中第i种部件可有可无;out[i]=0表示组装后的部件集合中没有第i种部件,out[i]=1表示组装后的集合中有第i种部件),以及组装效率。求怎样合理的分配N个车间之间的流量,使得组装效率最大。

题目分析

    在本题中的最大效率,可以视为各个车间构成的网络图的最大流量。那么,如何构造网络流图求出最大流量呢? 

    首先考虑将每个车间视为一个节点,若车间A的组装后的部件集合可以被车间B接受,那么单向连接车间A和B。但是,若车间A连接了车间B和车间C,那么A->B和A->C之间的路径容量无法控制。所以这种建图方式不好。 
    再考虑将每个车间拆分为两个节点,一个入节点,表示车间的组装原部件集合,一个出节点,表示车间组装后的部件集合,在入节点和出节点之间用一条容量为K的路径连接起来。若车间A的组装后部件集合可以被车间B的组装原部件集合所接受,那么连接车间A的出节点和车间B的入节点,同时,容量设为无穷大,这是因为车间的效率受其原部件-->组装后部件的组装效率决定,即车间的入节点到出节点的容量决定。 
    在构造好的图上从源点到汇点找最大流量,即为最大效率。

实现

#include
#include
#include
#include
using namespace std;#define MAX_NODE 150#define MAX_EDGE_NUM 300#define INFINITE 1 << 25#define min(a, b) a
& p){ return from == p.first && to == p.second; }};Edge gEdges[MAX_EDGE_NUM];int gEdgeCount;int gFlow[MAX_NODE][MAX_NODE];int gGap[MAX_NODE];int gDist[MAX_NODE];int gHead[MAX_NODE];int gPre[MAX_NODE];int gPath[MAX_NODE];int gSource, gDestination;void InsertEdge(int u, int v, int w){ Edge* it = find(gEdges, gEdges + gEdgeCount, pair
(u, v)); if (it != gEdges + gEdgeCount){ it->w = w; } else{ int e1 = gEdgeCount; gEdges[e1].from = u; gEdges[e1].to = v; gEdges[e1].w = w; gEdges[e1].next = gHead[u]; gHead[u] = e1; gEdgeCount++; int e2 = gEdgeCount; gEdges[e2].from = v; gEdges[e2].to = u; gEdges[e2].w = 0; gEdges[e2].next = gHead[v]; gHead[v] = e2; gEdges[e1].rev = e2; gEdges[e2].rev = e1; gEdgeCount++; }}void Bfs(){ memset(gGap, 0, sizeof(gGap)); memset(gDist, -1, sizeof(gDist)); gGap[0] = 1; gDist[gDestination] = 0; queue
Q; Q.push(gDestination); while (!Q.empty()){ int n = Q.front(); Q.pop(); for (int e = gHead[n]; e != -1; e = gEdges[e].next){ int v = gEdges[e].to; if (gDist[v] >= 0) continue; gDist[v] = gDist[n] + 1; gGap[gDist[v]] ++; Q.push(v); } }}int ISAP(int n){ // n为节点的数目 Bfs(); int u = gSource; int e, d; int ans = 0; while (gDist[gSource] <= n){ if (u == gDestination){ //增广 int min_flow = INFINITE; for (e = gPath[u]; u != gSource; e = gPath[u = gPre[u]]){ //注意,先u = gPre[u], 再取 e = gPath[u] min_flow = min(min_flow, gEdges[e].w); } u = gDestination; for (e = gPath[u]; u != gSource; e = gPath[u = gPre[u]]){ gEdges[e].w -= min_flow; gEdges[gEdges[e].rev].w += min_flow; gFlow[gPre[u]][u] += min_flow; } ans += min_flow; } for (e = gHead[u]; e != -1; e = gEdges[e].next){ if (gEdges[e].w > 0 && gDist[u] == gDist[gEdges[e].to] + 1) break; } if (e >= 0){ //向前推进 gPre[gEdges[e].to] = u; //前一个点 gPath[gEdges[e].to] = e;//该点连接的前一个边 u = gEdges[e].to; } else{ d = n; for (e = gHead[u]; e != -1; e = gEdges[e].next){ if (gEdges[e].w > 0) //需要能够走通才行!! d = min(d, gDist[gEdges[e].to]); } if (--gGap[gDist[u]] == 0) //gap优化 break; gDist[u] = d+1; //重标号 ++gGap[gDist[u]]; //更新 gap!! if (u != gSource) u = gPre[u];//回溯 } } return ans;}struct Node{ int id; int p; int component[12]; bool CanConnect(const Node& node){ for (int i = 0; i < p; i++){ if (component[i] == 0 && node.component[i] == 1 || component[i] == 1 && node.component[i] == 0) return false; } return true; }};Node gNodes[MAX_NODE];void BuildGraph(int n){ for (int i = 2; i <= n + 1; i++){ if (gNodes[1].CanConnect(gNodes[i])) InsertEdge(1, i, INFINITE); } for (int i = n+2; i <= 2*n + 1; i++){ for (int j = 2; j <= n + 1; j++){ if (j + n != i && gNodes[i].CanConnect(gNodes[j])) InsertEdge(i, j, INFINITE); } } for (int i = n + 2; i <= 2 * n + 1; i++){ if (gNodes[i].CanConnect(gNodes[2*n+2])) InsertEdge(i, 2*n+2, INFINITE); }}void print_graph(int n){ for (int u = 1; u <= n; u++){ printf("node %d links to ", u); for (int e = gHead[u]; e != -1; e = gEdges[e].next) printf("%d(flow = %d) ", gEdges[e].to, gEdges[e].w); printf("\n"); }}int main(){ int p, n, w, u, v; while (scanf("%d %d", &p, &n) != EOF){ memset(gFlow, 0, sizeof(gFlow)); memset(gHead, -1, sizeof(gHead)); gEdgeCount = 0; int node_id = 1; //构造源点 gNodes[node_id].p = p; for (int i = 0; i < p; i++){ gNodes[node_id].component[i] = 0; } node_id++; for (int i = 0; i < n; i++){ scanf("%d", &w); u = node_id; gNodes[u].p = p; for (int k = 0; k < p; k++){ scanf("%d", &gNodes[u].component[k]); } v = node_id + n; gNodes[v].p = p; for (int k = 0; k < p; k++){ scanf("%d", &gNodes[v].component[k]); } node_id++; InsertEdge(u, v, w); } node_id = 2 * n + 2; gNodes[node_id].p = p; for (int i = 0; i < p; i++){ //构造汇点 gNodes[node_id].component[i] = 1; } gSource = 1; gDestination = 2 * n + 2; BuildGraph(n);// print_graph(2 * n + 2); int result = ISAP(2 * n + 2); printf("%d", result); int count = 0; vector
> edge_vec; for (int i = n + 2; i <= 2 * n + 1; i++){ for (int j = 2; j <= n + 1; j++){ if (i != j + n && gFlow[i][j] > 0){ count++; edge_vec.push_back(pair
(i, j)); } } } printf(" %d\n", count); for (int k = 0; k < count; k ++){ int i = edge_vec[k].first; int j = edge_vec[k].second; printf("%d %d %d\n", i - n - 1, j - 1, gFlow[i][j]); } } return 0;}

 

转载地址:http://mklxl.baihongyu.com/

你可能感兴趣的文章
Java集合类的使用
查看>>
Axios源码分析
查看>>
RAC的函数式编程
查看>>
WEB安全知多少
查看>>
scheduleWithFixedDelay和scheduleAtFixedRate源码分析
查看>>
Arts 第十周(5/20 ~ 5/26)
查看>>
伸缩Kubernetes到2500个节点中遇到的问题和解决方法
查看>>
java版spring cloud+spring boot+redis多租户社交电子商务平台 (六)分布式配置中心(Spring Cloud Config)...
查看>>
[MySQL光速入门]014 试题答案
查看>>
区块链软件公司:未来金融与经济新格局是什么样的?
查看>>
前端要不要学数据结构&算法
查看>>
使用BCH提供的客户端将消息绑定到任何位置
查看>>
java B2B2C 多租户电子商城系统
查看>>
面试算法
查看>>
BCH应用热潮助力BCH生态壮大
查看>>
大数据基础知识全集,大数据爱好者收藏必备
查看>>
Mongodb副本集实现
查看>>
我的友情链接
查看>>
Oracle查询中rownum与Order by查询的关系(取数据的前几条)
查看>>
一起研究系列:LINUX目录介绍
查看>>