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
2 1 1
有N个city,m条路线,每条路线有一个花费;
输入 n,m;
下面是m行,每行三个数字,a,b,c;
表示有a到b,路长度为C
最后一行两个数字,A,B
问有A到B,路径最短,花费最小,的路线哟多少条
1 求出最短路径d1(由A出发的最短路径),d2(由B出发的最短路径),
2 删除非最短路径的边 (d1【a】+d2【b】+c==d1【B])
3 计算最大流,即将最短路径的路线加入();
#include <iostream> #include <stdio.h> #include <queue> #include <string.h> #include <vector> const int maxn=1e5+10; const int inf=0x3f3f3f3f; using namespace std; struct edge { int v,cost; edge (int _v=0,int _cost=0):v(_v),cost(_cost) {} }; int V; vector<edge>G[maxn]; int d[maxn]; void add_edge1(int from,int to,int w) { edge e; e.v=to; e.cost=w; G[from].push_back(e); } bool vis[maxn]; int cnt[maxn]; int dist[maxn]; void dijkstra(int s) { memset(vis,false,sizeof(vis)); for(int i=0; i<=V; i++) d[i]=inf; d[s]=0; vis[s]=true; queue<int>que; while(!que.empty()) que.pop(); que.push(s); memset(cnt,0,sizeof(cnt)); cnt[s]=1; while(!que.empty()) { int u=que.front(); que.pop(); vis[u]=false; for(int i=0; i<G[u].size(); i++) { int v=G[u][i].v; if(d[v]>d[u]+G[u][i].cost) { d[v]=d[u]+G[u][i].cost; if(!vis[v]) { vis[v]=true; que.push(v); } } } } } int a[maxn],b[maxn],c[maxn]; int d1[maxn],d2[maxn]; ///ISAP const int maxm=400010; struct Edge { int to,next,cap,flow; }edgeflow[maxm]; int tol; int head[maxn]; int gap[maxn],dep[maxn],pre[maxn],cur[maxn]; void init() { tol=0; memset(head,-1,sizeof(head)); } void add_edgef(int from,int to,int w,int rw=0) { edgeflow[tol].to=to; edgeflow[tol].cap=w; edgeflow[tol].next=head[from]; edgeflow[tol].flow=0; head[from]=tol++; edgeflow[tol].to=from; edgeflow[tol].cap=rw; edgeflow[tol].next=head[to]; edgeflow[tol].flow=0; head[to]=tol++; } int sap(int start,int end) { int N=V; memset(gap,0,sizeof(gap)); memset(dep,0,sizeof(dep)); memset(cur,0,sizeof(cur)); int u=start; pre[u]=-1; gap[0]=N; int ans=0; while(dep[start]<N) { if(u==end) { int Min=inf; for(int i=pre[u];i!=-1;i=pre[edgeflow[i^1].to]) if(Min>edgeflow[i].cap-edgeflow[i].flow) Min=edgeflow[i].cap-edgeflow[i].flow; for(int i=pre[u];i!=-1;i=pre[edgeflow[i^1].to]) { edgeflow[i].flow+=Min; edgeflow[i^1].flow-=Min; } u=start; ans+=Min; continue; } bool flag=false; int v; for(int i=cur[u];i!=-1;i=edgeflow[i].next) { v=edgeflow[i].to; if(edgeflow[i].cap-edgeflow[i].flow&&dep[v]+1==dep[u]) { flag=true; cur[u]=pre[v]=i; break; } } if(flag) { u=v; continue; } int Min=N; for(int i=head[u];i!=-1;i=edgeflow[i].next) { if(edgeflow[i].cap-edgeflow[i].flow&&dep[edgeflow[i].to]<Min) { Min=dep[edgeflow[i].to]; cur[u]=i; } } gap[dep[u]]--; if(!gap[dep[u]]) return ans; dep[u]=Min+1; gap[dep[u]]++; if(u!=start) u=edgeflow[pre[u]^1].to; } return ans; } int main() { int m; int t,A,B; cin>>t; while(t--) { init(); scanf("%d%d",&V,&m); for(int i=0; i<=V; i++) G[i].clear(); for(int i=0; i<m; i++) { scanf("%d%d%d",&a[i],&b[i],&c[i]); add_edge1(a[i],b[i],c[i]); } scanf("%d%d",&A,&B); dijkstra(A); memcpy(d1,d,sizeof(d)); for(int i=0; i<=V; i++) G[i].clear(); for(int i=0; i<m; i++) add_edge1(b[i],a[i],c[i]); dijkstra(B); memcpy(d2,d,sizeof(d)); for(int i=0; i<m; i++) { if(a[i]!=b[i]&&d1[a[i]]+d2[b[i]]+c[i]==d1[B]) add_edgef(a[i],b[i],1); } int ans=sap(A,B); printf("%d\n",ans); } return 0; }