给出一个有向图和起点、终点,每条路径只能走一次,询问从起点到终点能重复的走几次。
做法就是从起点到终点来回跑两遍最短路,建一个最短路网络流图。
无需考虑重边和自环,这些不影响Dinic算法的执行。
#include<bits/stdc++.h> using namespace std; const int maxn=2e5+100; const int inf=1e9+100; int n,m; struct node { int u,v,w,nxt; }edge[maxn<<1]; int head[maxn],tot; void addedge (int u,int v,int w) { edge[tot].u=u; edge[tot].v=v; edge[tot].w=w; edge[tot].nxt=head[u]; head[u]=tot++; } int dep[maxn],inq[maxn],cur[maxn],wjm,maxflow,s,t; bool bfs () { for (int i=0;i<=t;i++) { cur[i]=head[i]; dep[i]=inf; inq[i]=0; } dep[s]=0; queue<int> q; q.push(s); while (q.size()) { int u=q.front(); q.pop(); inq[u]=0; for (int i=head[u];i!=-1;i=edge[i].nxt) { int v=edge[i].v; if (dep[v]>dep[u]+1&&edge[i].w) { dep[v]=dep[u]+1; if (inq[v]==0) { q.push(v); inq[v]=1; } } } } if (dep[t]!=inf) return 1; return 0; } int dfs (int u,int flow) { int increase=0; if (u==t) { wjm=1; maxflow+=flow; return flow; } int used=0; for (int i=cur[u];i!=-1;i=edge[i].nxt) { cur[u]=i; int v=edge[i].v; if (edge[i].w&&dep[v]==dep[u]+1) { if (increase=dfs(v,min(flow-used,edge[i].w))) { used+=increase; edge[i].w-=increase; edge[i^1].w+=increase; if (used==flow) break; } } } return used; } int Dinic () { while (bfs()) { wjm=1; while (wjm==1) { wjm=0; dfs(s,inf); } } return maxflow; } long long d[maxn][2]; int vis[maxn]; struct qnode { int v; int w; qnode (int vv,int ww) { v=vv; w=ww; } bool operator < (const qnode &r) const { return w>r.w; } }; void dij (int s,int f) { for (int i=1;i<=n;i++) d[i][f]=inf,vis[i]=0; priority_queue<qnode> q; d[s][f]=0; q.push(qnode(s,d[s][f])); while (q.size()) { qnode tt=q.top(); q.pop(); int u=tt.v; vis[u]=1; for (int i=head[u];i!=-1;i=edge[i].nxt) { int v=edge[i].v; if (vis[v]) continue; if (d[u][f]+edge[i].w<d[v][f]) { d[v][f]=d[u][f]+edge[i].w; q.push(qnode(v,d[v][f])); } } } } struct E { int u,v,w; bool operator < (const E &r) const { return w<r.w; } }e[maxn]; int F[maxn]; int main () { int _; scanf("%d",&_); while (_--) { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) head[i]=-1,tot=0; for (int i=1;i<=m;i++) F[i]=0; for (int i=1;i<=m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); e[i]={u,v,w}; } sort(e+1,e+m+1); for (int i=1;i<=m;i++) { if (e[i].u==e[i].v) continue; addedge(e[i].u,e[i].v,e[i].w); } int A,B; scanf("%d%d",&A,&B); dij(A,0); for (int i=0;i<=n+1;i++) head[i]=-1;tot=0; for (int i=1;i<=m;i++) { if (e[i].u==e[i].v) continue; addedge(e[i].v,e[i].u,e[i].w); } dij(B,1); s=0;t=n+1; for (int i=0;i<=n+1;i++) head[i]=-1;tot=0;wjm=0;maxflow=0; addedge(s,A,inf);addedge(A,s,0); for (int i=1;i<=m;i++) { int u=e[i].u,v=e[i].v,w=e[i].w; if (u==v) continue; if (d[u][0]+w+d[v][1]==d[B][0]) { addedge(u,v,1); addedge(v,u,0); } } addedge(B,t,inf);addedge(t,B,0); printf("%d ",Dinic()); } }