从城市A到B,每次都走最短路,但每条边最多走一次,能够走多少次
曾做过一次这种题。建最短路树,跑SPFA
值得注意的是,如果跑dij的时候不建立永久标号,会导致最短路树出错
spfa要不停的进行松弛操作,同理不能这样建最短路树。看网上代码spfa都是正着反着跑两遍spfa,然后判断dis1[u]+dis2[v]+w==dis[B]是否成立。若成立,则u,v为最短路上的边
把网上的和我的都交了一遍,我的更快*_*
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<vector> using namespace std; const int maxn=1008; const int maxm=100008; const int INF=0x7f7f7f7f; struct shit{ int v,w; bool operator<(const shit &a) const { return w>a.w; } }; struct fuck{ int u,v,cap,next; }edge[maxm<<2]; vector<shit> g[maxn]; int dis[maxn]; vector<int> distree[maxn]; bool vis[maxn]; int head[maxn]; int tol; void init() { tol=0; memset(head,-1,sizeof(head)); } void addedge(int u,int v,int w) { edge[tol].u=u; edge[tol].v=v; edge[tol].cap=w; edge[tol].next=head[u]; head[u]=tol++; edge[tol].u=v; edge[tol].v=u; edge[tol].cap=0; edge[tol].next=head[v]; head[v]=tol++; } int last; int dep[maxn],gap[maxn]; void bfs(int sour,int sink) { queue<int> q; int i,u,v; memset(dep,-1,sizeof(dep)); memset(gap,0,sizeof(gap)); q.push(sink);dep[sink]=0;gap[0]=1; while(!q.empty()) { u=q.front();q.pop(); for(i=head[u];i!=-1;i=edge[i].next) { v=edge[i].v; if(dep[v]==-1&&edge[i].cap==0) { dep[v]=dep[u]+1; q.push(v); gap[dep[v]]++; } } } } int sap(int sour,int sink,int n) { bfs(sour,sink); int max_flow=0,top=0,i,u; int S[maxn],cur[maxn]; for(i=0;i<=n;i++) cur[i]=head[i]; u=sour; while(dep[u]<last) { if(u==sink) { int temp=INF,inser; for(i=0;i<top;i++) if(edge[S[i]].cap<temp) { temp=edge[S[i]].cap; inser=i; } for(i=0;i<top;i++) { edge[S[i]].cap-=temp; edge[S[i]^1].cap+=temp; } max_flow+=temp; top=inser; u=edge[S[top]].u; } if(u!=sink&&gap[dep[u]-1]==0) break; for(i=cur[u];i!=-1;i=edge[i].next) if(edge[i].cap>0&&dep[u]==dep[edge[i].v]+1) break; if(i!=-1) { cur[u]=i; S[top++]=i; u=edge[i].v; } else { int mi=last; for(i=head[u];i!=-1;i=edge[i].next) if(edge[i].cap>0&&dep[edge[i].v]<mi) { mi=dep[edge[i].v]; cur[u]=i; } gap[dep[u]]--; dep[u]=mi+1; gap[dep[u]]++; if(u!=sour) u=edge[S[--top]].u; } } return max_flow; } void dfs(int u) { int i,v; vis[u]=true; last++; for(i=0;i<distree[u].size();i++) { v=distree[u][i]; addedge(u,v,1); if(!vis[v]) dfs(v); } } int dij(int sour,int sink) { bool done[maxn]; priority_queue<shit> q; int i,u,v,w; shit pp; pp.v=sour;pp.w=0; q.push(pp); memset(dis,INF,sizeof(dis)); memset(done,false,sizeof(done)); dis[sour]=0; while(!q.empty()) { pp=q.top();q.pop(); u=pp.v; if(done[u]) continue;//永久标号没有wa数发 done[u]=true; for(i=0;i<g[u].size();i++) { v=g[u][i].v;w=g[u][i].w; if(dis[v]==dis[u]+w) distree[v].push_back(u); else if(dis[v]>dis[u]+w) { dis[v]=dis[u]+w; pp.v=v;pp.w=dis[v]; q.push(pp); distree[v].clear(); distree[v].push_back(u); } } } return dis[sink]; } int main() { int i,j,t,u,v,w,n,m; int sour,sink; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); shit pp; init(); for(i=1;i<=n;i++) { g[i].clear(); distree[i].clear(); } for(i=1;i<=m;i++) { scanf("%d%d%d",&u,&v,&w); pp.v=v;pp.w=w; g[u].push_back(pp);//曾建立无向边wa数发 } scanf("%d%d",&sour,&sink); int bitch=dij(sour,sink); if(bitch==INF) { printf("0 "); continue; } memset(vis,false,sizeof(vis)); last=0; dfs(sink); bitch=sap(sink,sour,n); printf("%d ",bitch); } return 0; }