SGU 185 Two shortest 最短路+最小费用最大流 或者 最短路+最大流
来源:互联网 发布:南京栖霞区网络问政 编辑:程序博客网 时间:2024/05/17 03:57
真心服了此题了
此题最贱之处在于内存只给了4M,也就是你只能开100W左右的int
我开了各种short 最后发现 short会莫名其妙变成4字节的去
然后就杯具了,MLE,开小了就会RE
这题明显不能用裸费用流去做了,裸费用流加的边太多了。任意两个点之间都来俩边的话一下子就给超内存了。
所以只好用最短路+费用流的方法去做。
不想写最短路+最大流的原因是 因为我的最大流模板太臃肿了 ,虽然至今没被卡过时,但是还是编程复杂度太高
于是决定偷了庄神 lost神牛的ISAP模板一个 http://www.zlinkin.com/?p=34 以后改造一下自己用
目测很短吧, 那是因为使用DFS的原因,而我那个模板是BFS无递归版本的。
#include <iostream>#include <algorithm>#include <cstring>#include <string>#include <cstdio>#include <cmath>#include <queue>#include <map>#include <set>#define eps 1e-5#define MAXN 404#define MAXM 160005#define INF 10007using namespace std;typedef int type;struct EDGE{ int v, next; type w;} edge[MAXM];int head[MAXN], e;inline void init(){ memset(head, -1, sizeof(head)); e = 0;}inline void add(int u, int v, type w){ edge[e].v = v; edge[e].w = w; edge[e].next = head[u]; head[u] = e++; edge[e].v = u; edge[e].w = 0; edge[e].next = head[v]; head[v] = e++;}int n;int h[MAXN];int gap[MAXN];int src, des;inline type dfs(int pos, type cost){ if (pos == des) return cost; int j, minh = n - 1; type lv = cost, d; for (j = head[pos]; j != -1; j = edge[j].next) { int v = edge[j].v; type w = edge[j].w; if(w > 0) { if (h[v] + 1 == h[pos]) { if (lv < edge[j].w) d = lv; else d = edge[j].w; d = dfs(v, d); edge[j].w -= d; edge[j ^ 1].w += d; lv -= d; if (h[src] >= n) return cost - lv; if (lv == 0) break; } if (h[v] < minh) minh = h[v]; } } if (lv == cost) { --gap[h[pos]]; if (gap[h[pos]] == 0) h[src] = n; h[pos] = minh + 1; ++gap[h[pos]]; } return cost - lv;}type sap(){ type ret = 0; memset(gap, 0, sizeof(gap)); memset(h, 0, sizeof(h)); gap[0] = n; while (h[src] < n) ret += dfs(src, INF); return ret;}整个模板里先init初始化,然后src,des, n 自己指定, 一般标号从1开始
然后这题我先用了一次spfa
将最短路求出来
然后跑一次最小费用最大流,看是否等于最短路的二倍,然后DFS之类的。
建最小费用的图时,注意使用SPFA求出来的最短路边集去建立,就是dis[i] + g[i][j] = dis[j]这样的边
可以想到的是这样的边明显会比整个图的边要少一半以上 而不至于去MLE
#include <iostream>#include <algorithm>#include <cstring>#include <string>#include <cstdio>#include <cmath>#include <queue>#include <map>#include <set>#define eps 1e-5#define MAXN 404#define MAXM 160005#define INF 10007using namespace std;struct EDGE{ short v, cap, cost; int next;} edge[MAXM];int n, m, ans, flow, src, des;int e, head[MAXN];int que[MAXN], pre[MAXN], dis[MAXN];bool vis[MAXN];short g[MAXN][MAXN];void init(){ e = ans = flow = 0; memset(head, -1, sizeof(head));}void add(short u, short v, short cap, short cost){ edge[e].v = v; edge[e].cap = cap; edge[e].cost = cost; edge[e].next = head[u]; head[u] = e++;}void addEdge(short u, short v, short cap, short cost){ add(u, v, cap, cost); add(v, u, 0, -cost);}bool spfa(){ int i, h = 0, t = 1; for(i = 0; i <= n; i ++) { dis[i] = 1000000007; vis[i] = false; } dis[src] = 0; que[0] = src; vis[src] = true; while(t != h) { int u = que[h++]; h %= n; vis[u] = false; for(i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].v; if(edge[i].cap && dis[v] > dis[u] + edge[i].cost) { dis[v] = dis[u] + edge[i].cost; pre[v] = i; if(!vis[v]) { vis[v] = true; que[t++] = v; t %= n; } } } } if(dis[des] == 1000000007) return false; return true;}void end(){ int u, p; short mi = 100; for(u = des; u != src; u = edge[p ^ 1].v) { p = pre[u]; mi = min(mi, edge[p].cap); } for(u = des; u != src; u = edge[p ^ 1].v) { p = pre[u]; edge[p].cap -= mi; edge[p ^ 1].cap += mi; ans += mi * edge[p].cost; // cost记录的为单位流量费用,必须得乘以流量。 } flow += mi;}int nt;void build1(){ short x, y, w; scanf("%d%d", &nt, &m); for(int i = 1; i <= m; i++) { scanf("%hd%hd%hd", &x, &y, &w); add(x, y, 1, w); add(y, x, 1, w); g[x][y] = g[y][x] = w; } src = 1; des = nt; n = des;}void build2(){ for(short i = 1; i <= nt; i++) for(short j = 1; j <= nt; j++) if(g[i][j] && dis[i] + g[i][j] == dis[j]) { addEdge(i, j, 1, g[i][j]); // printf("%d %d\n", i, j); } src = nt + 1; des = nt + 2; n = des; addEdge(src, 1, 2, 0); addEdge(nt, des, 2, 0);}void get(){ init(); build1(); spfa();}void MCMF2(){ init(); build2(); while(spfa()) end();}int flag;void dfs(int u){ printf(" %d", u); if(u == nt) { printf("\n"); flag = 1; return; } for(int i = head[u]; i != -1 && !flag; i = edge[i].next) if(edge[i].cap == 0 && i % 2 == 0) { if(edge[i].v > nt) return; edge[i].cap = -1; dfs(edge[i].v); }}int main(){ get(); int tmp = dis[des]; //printf("%d\n", tmp); MCMF2(); //printf("%d %d\n", tmp, ans); if(tmp * 2 == ans) { for(int i = head[1]; i != -1; i = edge[i].next) if(edge[i].cap == 0 && i % 2 == 0) { flag = 0; printf("1"); dfs(edge[i].v); } } else printf("No solution\n"); return 0;}
- SGU 185 Two shortest 最短路+最小费用最大流 或者 最短路+最大流
- SGU 185 Two shortest(最短路+最大流)
- SGU 185 Two shortest 最短路+最大流
- sgu 185 Two shortest(最短路+最大流)
- sgu 185(最短路+最大流)
- sgu185:Two shortest(最短路+最大流+邻接矩阵)
- SGU 185 Two shortest 最短路删边优化内存+网络流
- hdu 1280 Finding shortest path(最短路+最大流最小割)
- ZOJ 2760 How Many Shortest Path 最短路+最大流
- ZOJ 2760 How Many Shortest Path 最短路+最大流
- UVa 10806 Dijkstra, Dijkstra (无向图+最小费用最大流+最短路:)
- poj 2516 Minimum Cost(最小费用最大流 spfa算法求最短路)
- hdu3416(最短路+最大流)
- HDU5294(最短路,最大流)
- sgu 185 Two shortest 最大流
- [最小割最大流 || 最短路] roadblock Dinic && SPFA + SLE
- hdu 3416 最短路+最大流
- HDU 3416 最短路+最大流
- 第十章文档的压缩与打包
- 将 C++ 的成员函数作为回调函数
- 第十一章安装RPM包或者安装源码包
- 【HDU1686】Oulipo 思路+解题报告+代码+KMP算法个人理解 【0.5%达成】
- 第十二章 学习shell脚本之前的基础知识
- SGU 185 Two shortest 最短路+最小费用最大流 或者 最短路+最大流
- poj 2553 The Bottom of a Graph
- 在敏捷开发中如何维护文档
- SurfaceView和View最本质的区别
- 深圳手付通java面试题
- crontab使用说明及例子程序
- 华为boss力荐公司高层看的一篇文章,真的很经典!!![转载]
- commons-logging+log4j 简单的完整的日志操作实例
- 百度快照出问题投诉有没有用?