POJ2175_Evacuation Plan_消负圈的“更小”费用流
来源:互联网 发布:淘宝怎么上传视频凭证 编辑:程序博客网 时间:2024/05/21 08:16
题意
思路
要确定两类物体之间的对应关系,并希望使总花费最小的问题称为指派问题,一般可以用最小费用流来求解
添加一个源点一个汇点。
从源点向每幢大楼连一条容量为大楼内人数,费用为0的边。
从每个防空洞向汇点连一条容量为防空洞容量,费用为0的边。
在大楼和防空洞之间连边,容量为无穷,费用为两者之间的距离。
若求最佳方案,直接在这样建好的图上跑最小费用流就好了。
这个题如果直接跑最小费用流,再拿结果和原始方案对比的话,答案没错,问题是TLE。
注意题目要求的不是“最优”,而是”更优“,即比原始方案强就行了。
题目链接
http://poj.org/problem?id=2175
AC代码
#include<cstdio>#include<iostream>#include<cstring>#include<cstring>using namespace std;const int maxn = 100 + 10;const int maxv = 220;const int inf = 0x3f3f3f3f;int N, M;int X[maxn], Y[maxn], B[maxn]; //建筑的横、纵坐标,人数int P[maxn], Q[maxn], C[maxn]; //防空洞的横、纵坐标,容量int E[maxn][maxn]; //原始方案,从i建筑到j洞中的人数int g[maxv][maxv]; //花费矩阵(这里的花费等价于距离)int prev[maxv][maxv]; //从i到j的最短路径中,j的前驱bool usd[maxv]; //找环时用到的标记数组 //0~N表示建筑,N+1~N+M表示防空洞,N+M+1表示汇点int Abs(int x){ return x > 0 ? x : -x;}int main(){ cin >> N >> M; for(int i= 0; i< N; i++) cin >> X[i] >> Y[i] >> B[i]; for(int i= 0; i< M; i++) cin >> P[i] >> Q[i] >> C[i]; for(int i= 0; i< N; i++) for(int j= 0; j< M; j++) cin >> E[i][j]; int V = N + M + 1; //点的总数(添加一个超级汇点) memset(g, inf, sizeof g); //初始化距离为inf for(int j= 0; j< M; j++) //遍历防空洞 { int sum = 0; //进入这个洞的总人数 for(int i= 0; i< N; i++) //枚举建筑 { int c = Abs(X[i] - P[j]) + Abs(Y[i] - Q[j]) + 1;//求距离 g[i][N + j] = c; //从建筑到防空洞连一条边,花费为正 if(E[i][j] > 0) g[N + j][i] = -c; //原方案中有流量,从洞到建筑连一条边 //注意花费为负 sum += E[i][j]; } if(sum > 0) g[N + M][N + j] = 0; //原始方案中这个洞有人,从汇点向洞连一条边 if(sum < C[j]) g[N + j][N + M] = 0; //洞还没满,从洞向汇点连一条边 } for(int i= 0; i< V; i++) //从i到j最短路径中,j的前继初始化为i,即从i直接到j for(int j= 0; j< V; j++) prev[i][j] = i; for(int k= 0; k< V; k++) //floyd算法找负环 for(int i= 0; i< V; i++) for(int j= 0; j< V; j++) { if(g[i][j] > g[i][k] + g[k][j]) //可松弛 { g[i][j] = g[i][k] + g[k][j]; prev[i][j] = prev[k][j]; if(i == j && g[i][i] < 0) //用floyd算法找到负环的标志 { memset(usd, false, sizeof usd); //初始化标记数组 for(int v = i; !usd[v]; v = prev[i][v]) //沿着负环这条路径往前找 { usd[v] = true; //访问标记 if(v != N + M && prev[i][v] != N + M) //对于汇点不进行操作 { if(v >= N) E[prev[i][v]][v - N] ++; //表示防空洞的点 else E[v][prev[i][v] - N] --; //表示建筑的点 } //这里只改变1,因为题意是求一个更优方案,不需要最优 } printf("SUBOPTIMAL\n"); //输出原始方案非最优的结果 for(int x= 0; x< N; x++) for(int y= 0; y< M; y++) printf("%d%c", E[x][y], y + 1 == M ? '\n' : ' '); return 0; } } } printf("OPTIMAL\n"); //原始方案为最优 return 0;}
阅读全文
0 0
- POJ2175_Evacuation Plan_消负圈的“更小”费用流
- bzoj1075更快的zkw费用流
- 一种更高效的费用流算法——zkw费用流
- 更小的VertorDrawable
- 关于最大费用最大流的一类问题 【小谈】
- bzoj 3280: 小R的烦恼(费用流)
- [BZOJ3280]小R的烦恼(费用流)
- BZOJ网络流+费用流大合集:【3280小R的烦恼】
- 关于最大费用最大流的一类问题 【小谈】
- 更小的asp后门
- BZOJ 3280: 小R的烦恼 费用流 多路增广
- bzoj3280 小R的烦恼(费用流,类似餐巾计划)
- MATLAB的小程序(续更)
- 使用更小卷积核的作用
- poj 2185(流的最小费用的充要条件)消负圈
- BAPI_ACC_MANUAL_ALLOC_POST 费用分配函数的小bug及解决办法
- ZKW费用流的研究
- poj2516 基础的费用流
- 英文版 ubuntu不能输入中文问题及解决方案
- Visual C++ for Linux Development
- AFNetworking 的核心 AFURLSessionManager(二)
- Flume研究应用
- Properties是Hashtable的子类
- POJ2175_Evacuation Plan_消负圈的“更小”费用流
- 从0开始学OpenGL之Mac篇(1)
- 定义一个文件输入流,调用read(byte[] b)方法,将a.txt文件中的内容打印出来(byte数组大小限制为5)
- Tomcat在局域网中localhost可以访问,但是无法通过本地ip访问,127.0.0.1也无法访问问题的解决方法
- 改变标准输入输出流
- 得到-薛兆丰的北大经济学课-1-人性与稀缺
- 面试心得与总结---BAT、网易、蘑菇街
- CC3200 Simplelink Wi-Fi 入门指南
- Zookeeper集群搭建与启动