题意:从A走到B,有最短路,问这样不重复的最短路有几条
思路:先来讲选有效边,我们从start和end各跑一次最短路,得到dis1和dis2数组,如果dis1[u] + dis2[v] + cost[u][v] == dis1[end],那么uv这条边是最短路的一条边。然后我们选完边,把边加入ISAP,然后跑一边就行了...还没学过SAP只会敲模板....
错误思路:刚开始想的是先求出最短路,然后用费用流spfa去跑,边容量1,如果跑出一条路径费用等于最短路,那么路径+1,继续跑,但是超时了,看了半天是spfa跑费用流太慢的关系...等我学会网络流其他算法再来看这种emmm
代码:
#include<cstdio> #include<set> #include<cmath> #include<stack> #include<vector> #include<queue> #include<cstring> #include<string> #include<sstream> #include<iostream> #include<algorithm> #define ll long long using namespace std; const int maxn = 1000+5; const int INF = 0x3f3f3f3f; //网络流ISAP struct Node{ int to,next,cap,flow; }edge[200005]; int tot; int head[maxn]; int gap[maxn],dep[maxn],pre[maxn],cur[maxn]; void init(){ tot = 0; memset(head,-1,sizeof(head)); } void addEdge(int u,int v,int w,int rw = 0){ edge[tot].to = v; edge[tot].cap = w; edge[tot].flow = 0; edge[tot].next = head[u]; head[u] = tot++; edge[tot].to = u; edge[tot].cap = rw; edge[tot].flow = 0; edge[tot].next = head[v]; head[v] = tot++; } int sap(int start,int end,int N){ memset(gap,0,sizeof(gap)); memset(dep,0,sizeof(dep)); memcpy(cur,head,sizeof(head)); int u = start; pre[u] = -1; gap[u] = N; int ans = 0; while(dep[start] < N){ if(u == end){ int Min = INF; for(int i = pre[u];i != -1;i = pre[edge[i^1].to]){ if(Min > edge[i].cap - edge[i].flow){ Min = edge[i].cap - edge[i].flow; } } for(int i = pre[u];i != -1;i = pre[edge[i^1].to]){ edge[i].flow += Min; edge[i^1].flow -= Min; } u = start; ans += Min; continue; } bool flag = false; int v; for(int i = cur[u];i != -1;i = edge[i].next){ v = edge[i].to; if(edge[i].cap- edge[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 = edge[i].next){ if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min){ Min = dep[edge[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 = edge[pre[u]^1].to; } return ans; } struct road{ int v,cost,next; }e[200005]; int head2[maxn],tol,MinPath; void addRoad(int u,int v,int w){ e[tol].v = v; e[tol].cost = w; e[tol].next = head2[u]; head2[u] = tol++; } bool vis1[maxn]; int cnt[maxn],dist[maxn]; bool SPFA(int st,int n){ memset(vis1,false,sizeof(vis1)); for(int i = 0;i <= n;i++) dist[i] = INF; vis1[st] = true; dist[st] = 0; queue<int> q; while(!q.empty()) q.pop(); q.push(st); memset(cnt,0,sizeof(cnt)); cnt[st] = 1; while(!q.empty()){ int u = q.front(); q.pop(); vis1[u] = false; for(int i = head2[u];i != -1;i = e[i].next){ int v = e[i].v; if(dist[v] > dist[u] + e[i].cost){ dist[v] = dist[u] + e[i].cost; if(!vis1[v]){ vis1[v] = true; q.push(v); if(++cnt[v] > n) return false; } } } } return true; } int dis1[maxn]; int u[100005],v[100005],w[100005]; int main(){ int n,m,T; scanf("%d",&T); while(T--){ init(); scanf("%d%d",&n,&m); for(int i = 0;i < m;i++){ scanf("%d%d%d",&u[i],&v[i],&w[i]); } int st,en; scanf("%d%d",&st,&en); tol = 0; memset(head2,-1,sizeof(head2)); for(int i = 0;i < m;i++){ addRoad(u[i],v[i],w[i]); } SPFA(st,n); MinPath = dist[en]; memcpy(dis1,dist,sizeof(dist)); tol = 0; memset(head2,-1,sizeof(head2)); for(int i = 0;i < m;i++){ addRoad(v[i],u[i],w[i]); } SPFA(en,n); for(int i = 0;i < m;i++){ if(dis1[u[i]] + dist[v[i]] + w[i] == MinPath) addEdge(u[i],v[i],1); } int flow = sap(st,en,n); printf("%d ",flow); } return 0; }