https://vjudge.net/problem/UVA-1658
题意:
给出一个v个点e条边的有向加权图,求1~v的两条不相交(除了起点和终点外公共点)的路径,使得权和最小。
思路:
把2到v-1的每个点拆分为两个节点,容量为1,也就是只可以用一次,费用为0,然后求1到v的流量为2的最小费用流。
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 #include <vector> 5 #include <queue> 6 #include <cmath> 7 using namespace std; 8 9 const int maxn = 10000 + 5; 10 const int INF = 0x3f3f3f3f; 11 12 typedef long long LL; 13 14 struct Edge{ 15 int from, to, cap, flow, cost; 16 17 Edge(int u, int v, int c, int f, int w) :from(u), to(v), cap(c), flow(f), cost(w) {} 18 }; 19 20 struct MCMF 21 { 22 int n, m; 23 vector<Edge> edges; 24 vector<int> G[maxn]; 25 int inq[maxn]; 26 int d[maxn]; 27 int p[maxn]; 28 int a[maxn]; 29 30 void init(int n) 31 { 32 this->n = n; 33 for (int i = 0; i<n; i++) G[i].clear(); 34 edges.clear(); 35 } 36 37 void AddEdge(int from, int to, int cap, int cost) 38 { 39 edges.push_back(Edge(from, to, cap, 0, cost)); 40 edges.push_back(Edge(to, from, 0, 0, -cost)); 41 m = edges.size(); 42 G[from].push_back(m - 2); 43 G[to].push_back(m - 1); 44 } 45 46 bool BellmanFord(int s, int t, int &flow, LL & cost) 47 { 48 for (int i = 0; i<n; i++) d[i] = INF; 49 memset(inq, 0, sizeof(inq)); 50 d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF; 51 52 queue<int> Q; 53 Q.push(s); 54 while (!Q.empty()){ 55 int u = Q.front(); Q.pop(); 56 inq[u] = 0; 57 for (int i = 0; i<G[u].size(); i++){ 58 Edge& e = edges[G[u][i]]; 59 if (e.cap>e.flow && d[e.to]>d[u] + e.cost){ 60 d[e.to] = d[u] + e.cost; 61 p[e.to] = G[u][i]; 62 a[e.to] = min(a[u], e.cap - e.flow); 63 if (!inq[e.to]) { Q.push(e.to); inq[e.to] = 1; } 64 } 65 } 66 } 67 if (d[t] == INF) return false; 68 flow += a[t]; 69 cost += (LL)d[t] * (LL)a[t]; 70 for (int u = t; u != s; u = edges[p[u]].from){ 71 edges[p[u]].flow += a[t]; 72 edges[p[u] ^ 1].flow -= a[t]; 73 74 } 75 return true; 76 } 77 78 void MincostMaxdflow(int s, int t, int limit, LL & cost){ 79 int flow = 0; cost = 0; 80 while (BellmanFord(s, t, flow, cost) && flow < limit); 81 //return flow; 82 } 83 }t; 84 85 int main() 86 { 87 //freopen("D:\input.txt", "r", stdin); 88 int n, m; 89 while (~scanf("%d%d", &n, &m)) 90 { 91 t.init(2 * n - 2); 92 for (int i = 2; i <= n - 1; i++) 93 { 94 t.AddEdge(i - 1, n - 2 + i, 1, 0); 95 } 96 for (int i = 0; i<m; i++) 97 { 98 int u, v, w; 99 scanf("%d%d%d", &u, &v, &w); 100 v--; 101 if (u != 1 && u != n) u += n - 2; 102 else u--; 103 t.AddEdge(u, v, 1, w); 104 } 105 LL cost; 106 t.MincostMaxdflow(0, n - 1, 2, cost); 107 printf("%lld ", cost); 108 } 109 return 0; 110 }