/*
题意: 有 n 个城市,知道了起点和终点,有 m 条有向边,问从起点到终点的最短路一共有多少条。这是一个有向图,建边的时候要注意!!
解题思路:这题的关键就是找到哪些边可以构成最短路,其实之前做最短路的题目接触过很多,反向建一个图,求两边最短路,即从src到任一点的最短路dis1[]和从des到任一点的最短路dis2[],那么假设这条边是(u,v,w),如果dis1[u] + w + dis2[v] = dis1[des],说明这条边是构成最短路的边。找到这些边,就可以把边的容量设为1,跑一边最大流即可。
————————————————
代码:
1 #include<stdio.h> 2 #include<algorithm> 3 #include<string.h> 4 #include<queue> 5 using namespace std; 6 const int maxn = 1005; 7 const int inf = 0x3f3f3f3f; 8 int t, u, v, w; 9 struct node 10 { 11 int u, v, w, next; 12 }edge[800005], e[100005]; 13 int head[maxn], dis[2][maxn], pre[2][maxn],level[maxn]; 14 bool vis[maxn]; 15 int n, m, st, ed, tot; 16 void init() 17 { 18 tot = 0; 19 memset(head, -1, sizeof(head)); 20 memset(pre, -1, sizeof(pre)); 21 return; 22 } 23 void addedge(int u, int v, int w) 24 { 25 edge[tot].v = v; 26 edge[tot].w = w; 27 edge[tot].next = head[u]; 28 head[u] = tot++; 29 edge[tot].v = u; 30 edge[tot].w = w; 31 edge[tot].next = head[v]; 32 head[v] = tot++; 33 return; 34 } 35 void addedge1(int u,int v,int w) 36 { 37 edge[tot].v = v; 38 edge[tot].w = w; 39 edge[tot].next = pre[0][u]; 40 pre[0][u] = tot++; 41 return; 42 } 43 void addedge2(int u, int v, int w) 44 { 45 edge[tot].v = v; 46 edge[tot].w = w; 47 edge[tot].next = pre[1][u]; 48 pre[1][u] = tot++; 49 return; 50 } 51 void spfa(int st, int ed, int idx) 52 { 53 queue<int>pq; 54 memset(dis[idx], inf, sizeof(dis[idx])); 55 memset(vis, false, sizeof(vis)); 56 dis[idx][st] = 0; 57 pq.push(st); 58 vis[st] = true; 59 while (!pq.empty()) 60 { 61 int u = pq.front(); 62 pq.pop(); 63 vis[u] = false; 64 for (int i = pre[idx][u]; i != -1; i = edge[i].next) 65 { 66 int v = edge[i].v; 67 if(dis[idx][v] > dis[idx][u] + edge[i].w) 68 { 69 dis[idx][v] = dis[idx][u] + edge[i].w; 70 if (!vis[v]) 71 { 72 pq.push(v); 73 vis[v] = true; 74 } 75 } 76 } 77 } 78 } 79 void build() 80 { 81 for (int i = 1; i <= m; i++) 82 { 83 u = e[i].u; 84 v = e[i].v; 85 w = e[i].w; 86 if (dis[0][u] + dis[1][v] + w == dis[0][ed]) 87 { 88 addedge(u, v, 1); 89 } 90 } 91 } 92 int bfs(int st, int ed) 93 { 94 queue<int>q; 95 memset(level, 0, sizeof(level)); 96 level[st] = 1; 97 q.push(st); 98 while (!q.empty()) 99 { 100 int u = q.front(); 101 q.pop(); 102 if (u == ed) 103 { 104 return 1; 105 } 106 for (int i = head[u]; i != -1; i = edge[i].next) 107 { 108 int v = edge[i].v; 109 int w = edge[i].w; 110 if (level[v] == 0 && w != 0) 111 { 112 level[v] = level[u] + 1; 113 q.push(v); 114 } 115 } 116 } 117 return -1; 118 } 119 int dfs(int st, int ed, int f) 120 { 121 if (st == ed) 122 { 123 return f; 124 } 125 int ret = 0; 126 for (int i = head[st]; i != -1; i = edge[i].next) 127 { 128 int v = edge[i].v; 129 int w = edge[i].w; 130 if (level[v] == level[st] + 1 && w != 0) 131 { 132 int MIN = min(f - ret, w); 133 w = dfs(v, ed, MIN); 134 if (w > 0) 135 { 136 edge[i].w -= w; 137 edge[i ^ 1].w += w; 138 ret += w; 139 if (ret == f) 140 { 141 return ret; 142 } 143 } 144 else 145 { 146 level[v] = -1; 147 } 148 } 149 } 150 return ret; 151 } 152 int dinic(int st,int ed) 153 { 154 int ans = 0; 155 while (bfs(st, ed) != -1) 156 { 157 ans += dfs(st, ed, inf); 158 } 159 return ans; 160 } 161 int main() 162 { 163 //freopen("C:/input.txt", "r", stdin); 164 scanf("%d", &t); 165 while (t--) 166 { 167 init(); 168 scanf("%d%d", &n, &m); 169 for (int i = 1; i <= m; i++) 170 { 171 scanf("%d%d%d", &u, &v, &w); 172 e[i].u = u, e[i].v = v, e[i].w = w; 173 addedge1(u, v, w); 174 addedge2(v, u, w); 175 } 176 scanf("%d%d", &st, &ed); 177 spfa(st, ed, 0); 178 spfa(ed, st, 1); 179 build(); 180 int maxflow = dinic(st, ed); 181 printf("%d\n", maxflow); 182 } 183 return 0; 184 }View Code