题意:
给出m个路径的起点和终点还有长度
找出一条路径可以从1到n然后回到1..
并保证找到的路径是不重复而且是最短的..
思路:
容量控制经过只有1次
费用控制长度
在建完图后求最小费用最大流..
就可以找出最短距离..而且没有重复路径..
Tips:
※ 0点作为超级源点和1相连 n+1作为超级汇点和n相连 然后容量为2费用为0 保证一进一出
※ 建图的时候..相邻的正反边要紧挨着写..
因为更改图中的容量的时候..
edge[load[u]].c -= mn;
edge[load[u]^1].c += mn;
位运算表示的是反向边..所以加的时候应该紧挨着加..
※ 加边的时候..除了加已知的边 还要加入反向边 同时要加入容量为0 费用为负值的边..
所以每次运算的时候..应该先加入一条正向边 然后加入正向边的反向负值边
然后加入一条反向边 再加入反向边的反向负值边
Code:
1 #include <stdio.h> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 #define clr(x) memset(x, 0, sizeof(x)) 6 const int INF = 0x1f1f1f1f; 7 const int MAXN = 1010; 8 const int MAXM = 100010; 9 struct Edge 10 { 11 int to; 12 int next; 13 int c; 14 int f; 15 }edge[MAXM]; 16 int head[MAXN]; 17 int tot; 18 int n; 19 int dis[MAXN], load[MAXN], p[MAXN]; 20 bool flag[MAXN]; 21 22 void add(int s, int u, int c, int f) 23 { 24 edge[tot].to = u; 25 edge[tot].next = head[s]; 26 edge[tot].f = f; 27 edge[tot].c = c; 28 head[s] = tot++; 29 } 30 31 bool spfa(int s, int en) 32 { 33 int que[MAXN*10], qout, qin; 34 clr(flag); 35 memset(p, 0xff, sizeof(p)); 36 memset(load, 0xff, sizeof(load)); 37 memset(dis, INF, sizeof(dis)); 38 qin = qout = 0; 39 que[qin++] = s; 40 dis[s] = 0; 41 flag[s] = true; 42 while(qin != qout) { 43 int e = que[qout++]; 44 flag[e] = false; 45 for(int i = head[e]; i != -1; i=edge[i].next) { 46 if(edge[i].c) { 47 int ne = edge[i].to; 48 if(dis[ne]-dis[e] > edge[i].f) { 49 dis[ne] = dis[e]+edge[i].f; 50 p[ne] = e; 51 load[ne] = i; 52 if(!flag[ne]) { 53 flag[ne] = true; 54 que[qin++] = ne; 55 } 56 } 57 } 58 } 59 } 60 if(dis[en] == INF) 61 return false; 62 else return true; 63 } 64 65 int min_c_f(int s, int e) 66 { 67 int u, mn; 68 int ans_f = 0, ans_c = 0; 69 while(spfa(s, e)) 70 { 71 u = e; 72 mn = INF; 73 while(p[u] != -1) { 74 mn = min(edge[load[u]].c, mn); 75 u = p[u]; 76 } 77 u = e; 78 while(p[u] != -1) { 79 edge[load[u]].c -= mn; 80 edge[load[u]^1].c += mn; 81 u = p[u]; 82 } 83 ans_f += dis[e]*mn; 84 ans_c += mn; 85 } 86 return ans_f; 87 } 88 89 int main() 90 { 91 int i, j, k; 92 int m; 93 int a, b, l; 94 while(scanf("%d %d", &n, &m) != EOF) 95 { 96 clr(load), clr(dis), clr(p); 97 memset(head, 0xff, sizeof(head)); 98 tot = 0; 99 100 while(m--) { 101 scanf("%d %d %d", &a, &b, &l); 102 add(a, b, 1, l); 103 add(b, a, 0, -l); 104 add(b, a, 1, l); 105 add(a, b, 0, -l); 106 } 107 108 add(0, 1, 2, 0); 109 add(1, 0, 2, 0); 110 add(n, n + 1, 2, 0); 111 add(n+1, n , 2, 0); 112 int ans = min_c_f(0, n+1); 113 printf("%d\n", ans); 114 } 115 return 0; 116 }