【題意】:Farmer John(FJ)想帶他的朋友逛逛他的農場,給出n表示他農場的個數(1代表他的家,n代表谷倉),m表示建筑之間連接的路的個數。他想從他的家出發,然后通過一些農場,最后到達他的谷倉。然后,又從谷倉出發,通過一些農場,最后回到他的家。他要求旅游的路徑最短,并且不走重復的路。FJ確信總是存在可行解,問最短的路徑是多少?

【題解】:簡化問題,其實就是在不走重復的路的條件下,求兩次從1走到n的最短路。
              然后我們很容易就想到費用流,要找最短路徑,那顯然就是最小費用流。
              把路長看成費用,然后如果u和v之間有路(這里是雙向路),那么連邊u->v,v->u,費用都是路長,容量都為1,表示只能走一次。
              加入一個源點s,連邊s->1,費用為0,容量為2,表示增廣兩次,即求兩次最短路徑。
              匯點t直接就是n了。然后求s到t的最小費用流,最后的費用就是答案了。
              這題可以有點小優化,只需要記錄費用就可以了,因為最后的流肯定是2,而且每條邊的容量都是1,那么每一次增廣出來的流肯定為1,就不用每次比較取增廣路上最小的容量了。

【代碼】:
 1 #include "iostream"
 2 #include "cstdio"
 3 #include "string"
 4 #include "queue"
 5 using namespace std;
 6 #define bigint __int64
 7 #define maxn 1005
 8 #define maxm 40005
 9 const bigint INF = 99999999;
10 int n, m;
11 int s, t;
12 int eh[maxn], tot, p[maxn];
13 bigint dist[maxn], anscost;
14 bool visit[maxn];
15 
16 struct Edge {
17     int u, v;
18     bigint cost, cap, flow;
19     int next;
20 }et[maxm];
21 
22 void add(int u, int v,bigint cost, bigint cap,bigint flow) {
23     Edge e = {u, v, cost, cap, flow, eh[u]};
24     et[tot] = e;
25     eh[u] = tot++;
26 }
27 
28 void addedge(int u, int v, bigint cost, bigint cap) {
29     add(u, v, cost, cap, 0), add(v, u, -cost, 00);
30 }
31 
32 void init() {
33     tot = 0;
34     memset(eh, -1sizeof(eh));
35 }
36 
37 bool spfa() {
38     queue<int> que;
39     memset(visit, falsesizeof(visit));
40     memset(p, -1sizeof(p));
41     fill(&dist[0], &dist[maxn], INF);
42     visit[s] = true, dist[s] = 0;
43     que.push(s);
44     while(!que.empty()) {
45         int u = que.front();
46         que.pop();
47         visit[u] = false;
48         for(int i = eh[u]; i != -1; i = et[i].next) {
49             int v = et[i].v;
50             bigint cost = et[i].cost, cap = et[i].cap, flow = et[i].flow;
51             if(flow < cap && dist[u] + cost < dist[v]) {
52                 dist[v] = dist[u] + cost;
53                 p[v] = i;
54                 if(!visit[v]) {
55                     visit[v] = true;
56                     que.push(v);
57                 }
58             }
59         }
60     }
61     return dist[t] != INF;
62 }
63 
64 void costflow() {
65     anscost = 0;
66     while(spfa()) {
67         int x = p[t];
68         anscost += dist[t];
69         while(x != -1) {
70             et[x].flow++;
71             et[x^1].flow--;
72     //        et[x^1].cost = -et[x].cost;
73             x = p[et[x].u];
74         }
75     }
76 }
77 
78 int main() {
79     init();
80     int u, v;
81     bigint cost;
82     scanf("%d%d"&n, &m);
83     for(int i = 0; i < m; i++) {
84         scanf("%d%d%I64d"&u, &v, &cost);
85         addedge(u, v, cost, 1);
86         addedge(v, u, cost, 1);
87     }
88     s = 0, t = n;
89     addedge(s, 102);
90     costflow();
91     printf("%I64d\n", anscost);
92     return 0;
93 }