Uva 10806 来回最短路,不重复,MCMF

题目链接:https://uva.onlinejudge.org/external/108/10806.pdf

题意:无向图,从1到n来回的最短路,不走重复路。

分析:可以考虑为1到n的流量为2时的最小花费;

建图: 一个点到一个点的容量为1,费用为距离。

  1 #include <cstring>
  2 #include <cstdio>
  3 #include <vector>
  4 #include <queue>
  5 #include <algorithm>
  6 #include <iostream>
  7 using namespace std;
  8
  9 const int maxn = 100 + 10, INF = 1000000000;
 10
 11
 12 struct Edge
 13 {
 14     int from, to, cap, flow, cost;
 15 };
 16
 17 struct MCMF
 18 {
 19     int n, m;
 20     vector<Edge> edges;
 21     vector<int> G[maxn];
 22     bool inq[maxn];         // 是否在队列中
 23     int d[maxn];           // Bellman-Ford
 24     int p[maxn];           // 上一条弧
 25     int a[maxn];           // 可改进量
 26
 27     void init(int n)
 28     {
 29         this->n = n;
 30         for(int i = 0; i < n; i++) G[i].clear();
 31         edges.clear();
 32     }
 33
 34     void AddEdge(int from, int to, int cap, int cost)
 35     {
 36         edges.push_back((Edge)
 37         {
 38             from, to, cap, 0, cost
 39         });
 40         edges.push_back((Edge)
 41         {
 42             to, from, 0, 0, -cost
 43         });
 44         m = edges.size();
 45         G[from].push_back(m-2);
 46         G[to].push_back(m-1);
 47     }
 48
 49     bool BellmanFord(int s, int t, int &flow, long long& cost)
 50     {
 51         memset(inq,0,sizeof(inq));
 52         for(int i=0;i<n;i++)
 53             d[i] = INF;
 54         d[s] = 0;
 55         inq[s] = true;
 56         p[s] = 0;
 57         a[s] = INF;
 58
 59         queue<int> Q;
 60         Q.push(s);
 61         while(!Q.empty())
 62         {
 63             int u = Q.front();
 64             Q.pop();
 65             inq[u] = false;
 66             for(int i = 0; i < G[u].size(); i++)
 67             {
 68                 Edge& e = edges[G[u][i]];
 69                 if(e.cap > e.flow && d[e.to] > d[u] + e.cost)
 70                 {
 71                     d[e.to] = d[u] + e.cost;
 72                     p[e.to] = G[u][i];
 73                     a[e.to] = min(a[u], e.cap - e.flow);
 74                     if(!inq[e.to])
 75                     {
 76                         Q.push(e.to);
 77                         inq[e.to] = true;
 78                     }
 79                 }
 80             }
 81         }
 82         if(d[t] == INF) return false; //s-t 不连通,失败退出
 83         flow += a[t];
 84         cost += (long long)d[t] * (long long)a[t];
 85         int u = t;
 86         while(u != s)
 87         {
 88             edges[p[u]].flow += a[t];
 89             edges[p[u]^1].flow -= a[t];
 90             u = edges[p[u]].from;
 91         }
 92         return true;
 93     }
 94
 95      pair<long long,int>Mincost(int s, int t)
 96     {
 97         long long cost = 0;
 98         int flow = 0;
 99         while(BellmanFord(s, t, flow, cost));
100         return pair<long long ,int>{cost,flow};
101     }
102 };
103
104 MCMF solver;
105 int n;
106
107
108 int main()
109 {
110     while(true)
111     {
112         scanf("%d", &n);
113         if(n == 0) break;
114         solver.init(n + 1);
115         int m, from, to, cost;
116         scanf("%d", &m);
117         for(int i = 0; i < m; i++)
118         {
119             scanf("%d%d%d", &from, &to, &cost);
120             solver.AddEdge(from, to, 1, cost);
121             solver.AddEdge(to, from, 1, cost);
122         }
123         solver.AddEdge(0, 1, 2, 0);
124
125         pair<long long,int> ans = solver.Mincost(0, n);
126         int flow = ans.second;
127
128         if(flow != 2)
129             puts("Back to jail");
130         else
131             printf("%lld\n", ans.first);
132     }
133     return 0;
134 }
时间: 2024-08-07 04:09:27

Uva 10806 来回最短路,不重复,MCMF的相关文章

UVa 10806 Dijkstra, Dijkstra (最小费用流)

Dijkstra, Dijkstra Dexter: “You don’t understand. I can’t walk... they’ve tied my shoelaces together.” Topper Harley: “A knot. Bastards!” Jim Abrahams and Pat Proft, "Hot Shots! Part Deu Description you are a political prisoner in jail. Things are lo

uva 10806 Dijkstra, Dijkstra. (最小费最大流)

uva 10806 Dijkstra, Dijkstra. 题目大意:你和你的伙伴想要越狱.你的伙伴先去探路,等你的伙伴到火车站后,他会打电话给你(电话是藏在蛋糕里带进来的),然后你就能够跑去火车站了,那里有人接应你. 可是.由于你的伙伴跑去火车站的时候穿的是囚服,所以,他经过的街道都被戒严了,你必须从其它街道跑过去. 假设你能够到达火车站,请输出你和你的伙伴在路上花费的最短时间,假设不能请"Back to jail". 解题思路:最小费最大流.设置一个超级源点连向监狱(起点1), 容

POJ 2135 Farm Tour &amp;&amp; HDU 2686 Matrix &amp;&amp; HDU 3376 Matrix Again 费用流求来回最短路

累了就要写题解,最近总是被虐到没脾气. 来回最短路问题貌似也可以用DP来搞,不过拿费用流还是很方便的. 可以转化成求满流为2 的最小花费.一般做法为拆点,对于 i 拆为2*i 和 2*i+1,然后连一条流量为1(花费根据题意来定) 的边来控制每个点只能通过一次. 额外添加source和sink来控制满流为2. 代码都雷同,以HDU3376为例. #include <algorithm> #include <iostream> #include <cstring> #in

hdu 1535 Invitation Cards(有向图的来回最短路,要反向建图)

题目: 链接:点击打开链接 题意: 给一个图,求1到各点和各点到1最短路. 思路: 先spfa,然后反向建图,在spfa就行了. 代码: #include <iostream> #include <cstdio> #include <queue> #include <cstring> using namespace std; #define INF 100000000 const int N = 1000010; struct node{ int u,v,w

训练指南 UVA - 11374(最短路Dijkstra + 记录路径 + 模板)

layout: post title: 训练指南 UVA - 11374(最短路Dijkstra + 记录路径 + 模板) author: "luowentaoaa" catalog: true mathjax: true tags: - 最短路 - Dijkstra - 图论 - 训练指南 Airport Express UVA - 11374 题意 机场快线有经济线和商业线,现在分别给出经济线和商业线的的路线,现在只能坐一站商业线,其他坐经济线,问从起点到终点的最短用时是多少,还有

训练指南 UVA - 10917(最短路Dijkstra + 基础DP)

layout: post title: 训练指南 UVA - 10917(最短路Dijkstra + 基础DP) author: "luowentaoaa" catalog: true mathjax: true tags: - 最短路 - 基础DP - Dijkstra - 图论 - 训练指南 Walk Through the Forest UVA - 10917 题意 Jimmy打算每天沿着一条不同的路走,而且,他只能沿着满足如下条件的道路(A,B):存在一条从B出发回家的路径,比

训练指南 UVA - 11090(最短路BellmanFord+ 二分判负环)

layout: post title: 训练指南 UVA - 11090(最短路BellmanFord+ 二分判负环) author: "luowentaoaa" catalog: true mathjax: true tags: - 最短路 - 基础DP - BellmanFord - 图论 - 训练指南 Going in Cycle!! UVA - 11090 题意 就最小的环的平均权值 题解 分枚举平均值mid,只需判断是否存在平均值小于mid的回路,即判断是否有sum(wi)&

训练指南 UVA - 11478(最短路BellmanFord+ 二分+ 差分约束)

layout: post title: 训练指南 UVA - 11478(最短路BellmanFord+ 二分+ 差分约束) author: "luowentaoaa" catalog: true mathjax: true tags: - 最短路 - BellmanFord - 图论 - 训练指南 - 差分约束 Halum UVA - 11478 题意 带权有向图,每个点都可以有如下操作:令从ta出发的每一条边增加d,终止于ta的每一条边减小d 最后让所有边权的最小值非负且尽量大 题

UVA 10801 Dij最短路(改模板)

题意:有n个电梯,目的地是第K层(起点是第0层),给出每个电梯的速度,以及每个电梯能到达的层数,如果中途需要换电梯的话,时间需要+60,求到达目的地的最短时间: 思路:Dij求最短路.如果是另一条路比较短的话,相当于乘别的电梯,也就是再+60,自己不可能和自己比,即d[e.v] 和 d[e.u] + d + 60比较即可: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include