HDU-3416 Marriage Match IV(最短路,最大流)
题目链接:HDU-3416 Marriage Match IV
题意
给出一个有向图$G$,起点$s$和终点$t$,问$s$到$t$有多少条完全不同的最短路径(即长度相同,没有公共边)。
思路
求最短路的条数可以用最大流,不过要去掉原图中不可能属于最短路的边。
先用dijkstra求出各个点$u$与起点$s$的最短距离$dis[u]$,若一条边$(u,v,w)$满足$dis[v]-dis[u]==w$,说明这条边是$s\to v$最短路上的边,将这样的边加入流网络,容量为1,最后求出以起点$s$为源点终点$t$为汇点的最大流就是答案。
代码实现
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <utility> #include <vector> using std::pair; using std::queue; const int INF = 0x3f3f3f3f, N = 1100, M = 220000; int head[N], head2[N], d[N]; int s, t, tot, tot2, maxflow; typedef pair<int, int> P; int dis[N]; struct Edge { int to, cap, nex; } edge[M], edge2[M]; queue<int> q; void add2(int x, int y, int z) { edge2[++tot2].to = y, edge2[tot2].cap = z, edge2[tot2].nex = head2[x], head2[x] = tot2; } void dijkstra() { std::priority_queue<P, std::vector<P>, std::greater<P> > que; memset(dis, INF, sizeof(dis)); dis[s] = 0; que.push(P(0, s)); while (!que.empty()) { P p = que.top(); que.pop(); int v = p.second; if (p.first > dis[v]) continue; for (int i = head2[v], u; i; i = edge2[i].nex) { u = edge2[i].to; if (dis[v] + edge2[i].cap < dis[u]) { dis[u] = dis[v] + edge2[i].cap; que.push(P(dis[u], u)); } } } } void add(int x, int y, int z) { edge[++tot].to = y, edge[tot].cap = z, edge[tot].nex = head[x], head[x] = tot; edge[++tot].to = x, edge[tot].cap = 0, edge[tot].nex = head[y], head[y] = tot; } bool bfs() { memset(d, 0, sizeof(d)); while (q.size()) q.pop(); q.push(s); d[s] = 1; while (q.size()) { int x = q.front(); q.pop(); for (int i = head[x]; i; i = edge[i].nex) { int v = edge[i].to; if (edge[i].cap && !d[v]) { q.push(v); d[v] = d[x] + 1; if (v == t) return true; } } } return false; } int dinic(int x, int flow) { if (x == t) return flow; int rest = flow, k; for (int i = head[x]; i && rest; i = edge[i].nex) { int v = edge[i].to; if (edge[i].cap && d[v] == d[x] + 1) { k = dinic(v, std::min(rest, edge[i].cap)); if (!k) d[v] = 0; edge[i].cap -= k; edge[i^1].cap += k; rest -= k; } } return flow - rest; } void init() { tot = 1, tot2 = 0, maxflow = 0; memset(head, 0, sizeof(head)); memset(head2, 0, sizeof(head2)); } int main() { int T; scanf("%d", &T); while (T--) { int n, m; scanf("%d %d", &n, &m); init(); for (int i = 0, u, v, z; i < m; i++) { scanf("%d %d %d", &u, &v, &z); if (u == v) continue; add2(u, v, z); } scanf("%d %d", &s, &t); dijkstra(); for (int i = 1; i <= n; i++) { for (int j = head2[i], u; j; j = edge2[j].nex) { u = edge2[j].to; if (dis[u] - dis[i] == edge2[j].cap) add(i, u, 1); } } while (bfs()) maxflow += dinic(s, INF); printf("%d\n", maxflow); } return 0; }
作者:_kangkang
本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。