博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SGU 185.Two shortest (最小费用最大流)
阅读量:6288 次
发布时间:2019-06-22

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

时间限制:0.25s

空间限制:4M

题意:

       在n(n<=400)个点的图中,找到并输出两条不想交的最短路。不存在输出“No sulotion”;

 

 

 

 

 


 

Solution:

            最小费用最大流

            建图与poj 2135 一样,添加S到1的流量为2权为0,n到T的流量为2权为0的边,其它边的流量为1,权为路径长度.

            但是这道题麻烦不在要输出最短路,而在仅仅4M的内存上。

            由于只有4M,我们最多存上400*400条边.但是图却是一个无向图,朴素的想法是存上400*400*2条边,但是这里内存不够.

            所以我们首先要确定记录一条边我们是否使用过,如果使用了使用的是那个方向.

            相应的在找到增广路后,把正向反向边的流量改变,把反向边的费用变成负值.

            最后按照我们标记过的边dfs,并输出就好了.

            总的来说是一道足以加深对最小费用最大流的理解的不错的题!

 

参考代码:

/*       最小费用最大流算法:       思路:       以费用为权做最短路算法。*/#include 
#include
#include
#include
#include
using namespace std;const int INF = 409, Maxn = 0x3f3f3f3f;struct node { int u, v, t, c, next;} edge[INF * INF];int head[INF], nCnt = 1;int G[INF][INF];void addEdge (int u, int v, int traffic, int cost) { edge[++nCnt].v = v, edge[nCnt].u = u, edge[nCnt].t = traffic, edge[nCnt].c = cost; edge[nCnt].next = head[u], head[u] = nCnt; edge[++nCnt].v = u, edge[nCnt].u = v, edge[nCnt].t = traffic, edge[nCnt].c = cost; edge[nCnt].next = head[v], head[v] = nCnt;}int max_flow, min_cost;int n, m, SS, ST, S, T, min_dis = Maxn;int SPFA() { queue
ql; int vis[INF] = { 0}, dis[INF], pre[INF] = { 0}; ql.push (SS); memset (dis, 0x3f, sizeof dis); vis[SS] = 1, dis[SS] = 0; while (!ql.empty() ) { int x = ql.front(); ql.pop(); for (int i = head[x]; i != 0; i = edge[i].next) { if (edge[i].t == 0) continue; int v = edge[i].v, c = edge[i].c; if (dis[v] > dis[x] + c) { dis[v] = dis[x] + c; pre[v] = i; if (!vis[v]) ql.push (v), vis[v] = 1; } } vis[x] = 0; } min_dis = min (min_dis, dis[ST]); if (dis[ST] == Maxn) return 0; else { min_cost += dis[ST]; int k = pre[ST]; int cur_flow = Maxn; while (k) { if (cur_flow > edge[k].t) cur_flow = edge[k].t; G[edge[k].u][edge[k].v] = G[edge[k].v][edge[k].u] = 1 ^ G[edge[k].v][edge[k].u]; edge[k].t = edge[k ^ 1].t, edge[k].c = abs (edge[k].c); edge[k ^ 1].t = 0, edge[k ^ 1].c = -abs (edge[k ^ 1].c); k = pre[edge[k].u]; } max_flow += cur_flow; k = pre[ST]; while (k) { edge[k].t -= cur_flow, edge[k ^ 1].t += cur_flow; k = pre[edge[k].u]; } return 1; }}void dfs (int x) { for (int i = head[x]; i != 0; i = edge[i].next) { if (G[x][edge[i].v] && edge[i].t > 0 && edge[i].v < T) { edge[i].t = 0; dfs (edge[i].v); break; } } if (x == S) printf ("%d", x); else printf (" %d", x);}int MCMF() { while (SPFA() ); if (max_flow == 2 && min_cost == 2 * min_dis) { dfs (T); putchar (10); dfs (T); } else puts ("No solution");}void build() { scanf ("%d %d", &n, &m); int x, y, z; for (int i = 1; i <= m; i++) { scanf ("%d %d %d", &x, &y, &z); addEdge (x, y, 1, z); } S = 1, T = n; SS = n + 1, ST = n + 2; addEdge (SS, S, 2, 0), addEdge (T, ST, 2, 0);}int main() { build(); MCMF(); return 0;}
View Code

 

转载于:https://www.cnblogs.com/keam37/p/3982552.html

你可能感兴趣的文章
还原数据库
查看>>
作业调度框架 Quartz.NET 2.0 beta 发布
查看>>
mysql性能的检查和调优方法
查看>>
项目管理中的导向性
查看>>
Android WebView 学习
查看>>
(转)从给定的文本中,查找其中最长的重复子字符串的问题
查看>>
HDU 2159
查看>>
spring batch中用到的表
查看>>
资源文件夹res/raw和assets的使用
查看>>
UINode扩展
查看>>
LINUX常用命令
查看>>
百度云盘demo
查看>>
概率论与数理统计习题
查看>>
初学structs2,简单配置
查看>>
Laravel5.0学习--01 入门
查看>>
时间戳解读
查看>>
sbin/hadoop-daemon.sh: line 165: /tmp/hadoop-hxsyl-journalnode.pid: Permission denied
查看>>
@RequestMapping 用法详解之地址映射
查看>>
254页PPT!这是一份写给NLP研究者的编程指南
查看>>
《Data Warehouse in Action》
查看>>