[题解]uva 1658 Admiral

Posted 阿波罗2003

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[题解]uva 1658 Admiral相关的知识,希望对你有一定的参考价值。

vjudge传送门[here]


  题目大意:给一个有(3≤v≤1000)个点e(3≤e≤10000)条边的有向加权图,求1~v的两条不相交(除了起点和终点外没有公共点)的路径,使权值和最小。

  正解是吧2到v-1的每个点拆成两个点,中间连一条容量为1,费用为0的边,然后求1到v的流量为2的最小费用流就行了。

Code

  1 /**
  2  * Uva
  3  * Problem#1658
  4  * Accepted
  5  */
  6 #include<iostream>
  7 #include<cstdio>
  8 #include<cctype>
  9 #include<cstring>
 10 #include<cstdlib>
 11 #include<fstream>
 12 #include<sstream>
 13 #include<algorithm>
 14 #include<map>
 15 #include<set>
 16 #include<queue>
 17 #include<vector>
 18 #include<stack>
 19 using namespace std;
 20 typedef bool boolean;
 21 #define INF 0xfffffff
 22 #define smin(a, b) a = min(a, b)
 23 #define smax(a, b) a = max(a, b)
 24 template<typename T>
 25 inline boolean readInteger(T& u){
 26     char x;
 27     int aFlag = 1;
 28     while(!isdigit((x = getchar())) && x != - && ~x);
 29     if(x == -1){
 30         return false;
 31     }
 32     if(x == -){
 33         x = getchar();
 34         aFlag = -1;
 35     }
 36     for(u = x - 0; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - 0);
 37     ungetc(x, stdin);
 38     u *= aFlag;
 39     return true;
 40 }
 41 
 42 ///map template starts
 43 typedef class Edge{
 44     public:
 45         int end;
 46         int next;
 47         int cap;
 48         int flow;
 49         int cost;
 50         Edge(const int end = 0, const int next = 0, const int cap = 0, const int flow = 0, const int cost = 0):end(end), next(next), cap(cap), flow(flow), cost(cost){}
 51 }Edge;
 52 
 53 typedef class MapManager{
 54     public:
 55         int ce;
 56         int *h;
 57         Edge *edge;
 58         MapManager(){}
 59         MapManager(int points, int limit):ce(0){
 60             h = new int[(const int)(points + 1)];
 61             edge = new Edge[(const int)(limit + 1)];
 62             memset(h, 0, sizeof(int) * (points + 1));
 63         }
 64         inline void addEdge(int from, int end, int cap, int flow, int cost){
 65             edge[++ce] = Edge(end, h[from], cap, flow, cost);
 66             h[from] = ce;
 67         }
 68         inline void addDoubleEdge(int from, int end, int cap, int cost){
 69             addEdge(from, end, cap, 0, cost);
 70             addEdge(end, from, cap, cap, -cost);
 71         }
 72         Edge& operator [](int pos){
 73             return edge[pos];
 74         }
 75         inline int reverse(int pos){
 76             return (pos & 1) ? (pos + 1) : (pos - 1);
 77         }
 78         inline void clean(){
 79             delete[] h;
 80             delete[] edge;
 81             ce = 0;
 82         }
 83 }MapManager;
 84 #define m_begin(g, i) (g).h[(i)]
 85 /// map template ends
 86 
 87 int n, m;
 88 MapManager g;
 89 
 90 inline boolean init(){
 91     if(!readInteger(n))    return false;
 92     readInteger(m);
 93     g = MapManager(n * 2, m * 2 + n * 2);
 94     for(int i = 1, a, b, w; i <= m; i++){
 95         readInteger(a);
 96         readInteger(b);
 97         readInteger(w);
 98         g.addDoubleEdge(a + n, b, 1, w);
 99     }
100     for(int i = 1; i <= n; i++){            //拆点 
101         g.addDoubleEdge(i, i + n, 1, 0);
102     }
103     return true;
104 }
105 
106 int* dis;
107 boolean* visited;
108 int* last;
109 int* laste;
110 int* mflow;
111 int cost;
112 int s, t;
113 queue<int> que;
114 int sizee;
115 
116 inline void spfa(){
117     memset(dis, 0x7f, sizeof(int) * (sizee));
118     memset(visited, false, sizeof(boolean) * (sizee));
119     que.push(s);
120     last[s] = 0;
121     dis[s] = 0;
122     laste[s] = 0;
123     mflow[s] = INF;
124     visited[s] = true;
125     while(!que.empty()){
126         int e = que.front();
127         que.pop();
128         visited[e] = false;
129         for(int i = m_begin(g, e); i != 0; i = g[i].next){
130             int &eu = g[i].end;
131             if(dis[e] + g[i].cost < dis[eu] && g[i].flow < g[i].cap){
132                 dis[eu] = dis[e] + g[i].cost;
133                 last[eu] = e;
134                 laste[eu] = i;
135                 mflow[eu] = min(g[i].cap - g[i].flow, mflow[e]);
136                 if(!visited[eu] && eu != t){
137                     que.push(eu);
138                     visited[eu] = true;
139                 }
140             }
141         }
142     }
143     for(int i = t; i != s; i = last[i]){
144         g[laste[i]].flow += mflow[t];
145         g[g.reverse(laste[i])].flow -= mflow[t];
146         cost += mflow[t] * g[laste[i]].cost;
147     }
148 }
149 
150 inline void minCostFlow(){
151     s = 1 + n, t = n, sizee = 2 * n + 1;
152     dis = new int[(const int)(sizee)];
153     visited = new boolean[(const int)(sizee)];
154     last = new int[(const int)(sizee)];
155     laste = new int[(const int)(sizee)];
156     mflow = new int[(const int)(sizee)];
157     spfa();
158     spfa();
159 }
160 
161 inline void solve(){
162     cost = 0;
163     minCostFlow();
164     printf("%d\n", cost);
165     g.clean();
166 }
167 
168 int main(){
169     while(init()){
170         solve();        
171     }
172     return 0;
173 }

 

以上是关于[题解]uva 1658 Admiral的主要内容,如果未能解决你的问题,请参考以下文章

UVa 1658 - Admiral(最小费用最大流 + 拆点)

UVA - 1658 Admiral 海军上将

uva 1658 Admiral (最小费最大流)

UVa1658 Admiral (拆点法,最小费用流)

uva1658 Admiral

UVa 1658,Admiral (拆点+限制最小费用流)