hdu 3416 Marriage Match IV (最短路+最大流)
題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=3416
Do not sincere non-interference。
Like that show, now starvae also take part in a show, but it take place between city A and B. Starvae is in city A and girls are in city B. Every time starvae can get to city B and make a data with a girl he likes. But there are two problems with it, one is starvae must get to B within least time, it's said that he must take a shortest path. Other is no road can be taken more than once. While the city starvae passed away can been taken more than once.
So, under a good RP, starvae may have many chances to get to city B. But he don't know how many chances at most he can make a data with the girl he likes . Could you help starvae?
Input
The first line is an integer T indicating the case number.(1<=T<=65)
For each case,there are two integer n and m in the first line ( 2<=n<=1000, 0<=m<=100000 ) ,n is the number of the city and m is the number of the roads.
Then follows m line ,each line have three integers a,b,c,(1<=a,b<=n,0<c<=1000)it means there is a road from a to b and it's distance is c, while there may have no road from b to a. There may have a road from a to a,but you can ignore it. If there are two roads from a to b, they are different.
At last is a line with two integer A and B(1<=A,B<=N,A!=B), means the number of city A and city B.
There may be some blank line between each case.
Output
Output a line with a integer, means the chances starvae can get at most.
Sample Input
3 7 8 1 2 1 1 3 1 2 4 1 3 4 1 4 5 1 4 6 1 5 7 1 6 7 1 1 7 6 7 1 2 1 2 3 1 1 3 3 3 4 1 3 5 1 4 6 1 5 6 1 1 6 2 2 1 2 1 1 2 2 1 2
Sample Output
2 1 1
題意: 有 n 個城市,知道了起點和終點,有 m 條有向邊,問從起點到終點的最短路一共有多少條。
解題思路:這題的關鍵就是找到哪些邊可以構成最短路,其實之前做最短路的題目接觸過很多,反向建一個圖,求兩邊最短路,即從src到任一點的最短路dis1[]和從des到任一點的最短路dis2[],那麼假設這條邊是(u,v,w),如果dis1[u] + w + dis2[v] = dis1[des],說明這條邊是構成最短路的邊。找到這些邊,就可以把邊的容量設為1,跑一邊最大流即可。
#include<stdio.h> #include<algorithm> #include<string.h> #include<queue> using namespace std; const int maxn = 1005; const int inf = 0x3f3f3f3f; int t, u, v, w; struct node { int u, v, w, next; }edge[800005], e[100005]; int head[maxn], dis[2][maxn], pre[2][maxn],level[maxn]; bool vis[maxn]; int n, m, st, ed, tot; void init() { tot = 0; memset(head, -1, sizeof(head)); memset(pre, -1, sizeof(pre)); return; } void addedge(int u, int v, int w) { edge[tot].v = v; edge[tot].w = w; edge[tot].next = head[u]; head[u] = tot++; edge[tot].v = u; edge[tot].w = w; edge[tot].next = head[v]; head[v] = tot++; return; } void addedge1(int u,int v,int w) { edge[tot].v = v; edge[tot].w = w; edge[tot].next = pre[0][u]; pre[0][u] = tot++; return; } void addedge2(int u, int v, int w) { edge[tot].v = v; edge[tot].w = w; edge[tot].next = pre[1][u]; pre[1][u] = tot++; return; } void spfa(int st, int ed, int idx) { queue<int>pq; memset(dis[idx], inf, sizeof(dis[idx])); memset(vis, false, sizeof(vis)); dis[idx][st] = 0; pq.push(st); vis[st] = true; while (!pq.empty()) { int u = pq.front(); pq.pop(); vis[u] = false; for (int i = pre[idx][u]; i != -1; i = edge[i].next) { int v = edge[i].v; if(dis[idx][v] > dis[idx][u] + edge[i].w) { dis[idx][v] = dis[idx][u] + edge[i].w; if (!vis[v]) { pq.push(v); vis[v] = true; } } } } } void build() { for (int i = 1; i <= m; i++) { u = e[i].u; v = e[i].v; w = e[i].w; if (dis[0][u] + dis[1][v] + w == dis[0][ed]) { addedge(u, v, 1); } } } int bfs(int st, int ed) { queue<int>q; memset(level, 0, sizeof(level)); level[st] = 1; q.push(st); while (!q.empty()) { int u = q.front(); q.pop(); if (u == ed) { return 1; } for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].v; int w = edge[i].w; if (level[v] == 0 && w != 0) { level[v] = level[u] + 1; q.push(v); } } } return -1; } int dfs(int st, int ed, int f) { if (st == ed) { return f; } int ret = 0; for (int i = head[st]; i != -1; i = edge[i].next) { int v = edge[i].v; int w = edge[i].w; if (level[v] == level[st] + 1 && w != 0) { int MIN = min(f - ret, w); w = dfs(v, ed, MIN); if (w > 0) { edge[i].w -= w; edge[i ^ 1].w += w; ret += w; if (ret == f) { return ret; } } else { level[v] = -1; } } } return ret; } int dinic(int st,int ed) { int ans = 0; while (bfs(st, ed) != -1) { ans += dfs(st, ed, inf); } return ans; } int main() { //freopen("C:/input.txt", "r", stdin); scanf("%d", &t); while (t--) { init(); scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) { scanf("%d%d%d", &u, &v, &w); e[i].u = u, e[i].v = v, e[i].w = w; addedge1(u, v, w); addedge2(v, u, w); } scanf("%d%d", &st, &ed); spfa(st, ed, 0); spfa(ed, st, 1); build(); int maxflow = dinic(st, ed); printf("%d\n", maxflow); } return 0; }