题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=3416
有一个有向图,n个点,m条边,给一个起点和终点,求出从起点到终点的最短路共有几条,每条路只能走一次,每个点可以走多次;
先用spfa求出从起点到各点的距离dist,然后根据dist的值建立新的图,边权为1,套用Dinic模板求起点到终点的最大流即可;
#include <iostream> #include <stdio.h> #include <math.h> #include <string.h> #include <queue> #include <stack> #include <algorithm> #include <map> #include <string> typedef long long LL; #define INF 0x3f3f3f3f #define met(a, b) memset(a, b, sizeof(a)) #define N 200005 using namespace std; struct node { int v, w, Next; }G[N], e[N]; int n, m, dist[N], vis[N], A, B; int l[N]; int Head[N], cnt; void Add(int u, int v, int w) { G[cnt].v = v; G[cnt].w = w; G[cnt].Next = Head[u]; Head[u] = cnt++; } int Head1[N], cnt1; void Add1(int u, int v, int w) { e[cnt1].v = v; e[cnt1].w = w; e[cnt1].Next = Head1[u]; Head1[u] = cnt1++; } void spfa() { for(int i=1; i<=n; i++) dist[i] = INF; met(vis, 0); queue<int>Q; Q.push(A); vis[A] = 1; dist[A] = 0; while(!Q.empty()) { int p = Q.front();Q.pop(); vis[p] = 0; for(int i=Head[p]; i!=-1; i=G[i].Next) { int q = G[i].v; if(dist[q] > dist[p]+G[i].w) { dist[q] = dist[p]+G[i].w; if(!vis[q]) { vis[q] = 1; Q.push(q); } } } } } bool bfs(int s, int End) { met(l, 0); queue<int>Q; Q.push(s); l[s] = 1; while(!Q.empty()) { int u = Q.front();Q.pop(); if(u == End)return true; for(int i=Head1[u]; i!=-1; i=e[i].Next) { int v = e[i].v; if(!l[v] && e[i].w) { l[v] = l[u]+1; Q.push(v); } } } return false; } int dfs(int u, int MaxFlow, int End) { if(u == End)return MaxFlow; int uflow = 0; for(int j=Head1[u]; j!=-1; j=e[j].Next) { int v = e[j].v; if(l[v]==l[u]+1 && e[j].w) { int flow = min(e[j].w, MaxFlow-uflow); flow = dfs(v, flow, End); e[j].w -= flow; e[j^1].w += flow; uflow += flow; if(uflow == MaxFlow) break; } } if(uflow == 0) l[u] = 0; return uflow; } int Dinic() { int MaxFlow = 0; while(bfs(A, B)) MaxFlow += dfs(A, INF, B); return MaxFlow; } int main() { int T; scanf("%d", &T); while(T--) { met(Head, -1); cnt = 0; met(Head1, -1); cnt1 = 0; scanf("%d %d", &n, &m); for(int i=1; i<=m; i++) { int u, v, w; scanf("%d %d %d", &u, &v, &w); if(u == v)continue; Add(u, v, w); } scanf("%d %d", &A, &B); spfa();///更新dist; for(int i=1; i<=n; i++) { for(int j=Head[i]; j!=-1; j=G[j].Next) { int v = G[j].v; if(dist[v] == dist[i]+G[j].w)///建立新的网络流图; { Add1(i, v, 1); Add1(v, i, 0); } } } int ans = Dinic();///求最大流即可; printf("%d ", ans); } return 0; }