标签:else spfa memset cost while nod 过程 style 结束
首先用spfa找一条最短路当然这个最短路是按照边的费用算的,在找的过程中,如果这条边的流量已经为0,就一定要放弃这个到达的点,也就是不仅判断dis,也要判断流量·。
其次,从这条路的结束点(汇点)往它的前驱回溯,找到这个路径上最小的流,每一个流都减去这个最小的流,总流量加上这个最小的流。
每一个边,都要用它的费用,乘上这个最小流量,加在一起。
直到不能再找到一条从源点到汇点的完整路径为止。
记得反向边的费用是负的费用,因为我们要给计算机一个后悔的机会。
代码如下:
#include<cstdio> #include<iostream> #include<queue> #include<cstring> using namespace std; #define inf 999999999 #define maxn 500000 struct node { int to,nxt=-1,w,flow,cost; } edge[maxn]; int head[maxn],pre[maxn],dis[maxn]; bool vis[maxn]; int s,t,n,m,cnt=-1,ans; void add(int a,int b,int z,int f) { edge[++cnt].to=b; edge[cnt].nxt=head[a]; head[a]=cnt; edge[cnt].w=z; edge[cnt].cost=f; } int spfa() { for(int i=1; i<=n; i++) { dis[i]=inf; vis[i]=0; pre[i]=-1; } queue<int> q; dis[s]=0; vis[s]=1; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u]; i!=-1; i=edge[i].nxt) { int to=edge[i].to; if(dis[to]>dis[u]+edge[i].cost&&edge[i].w>edge[i].flow) { dis[to]=dis[u]+edge[i].cost; pre[to]=i; if(!vis[to]) { q.push(to); vis[to]=1; } } } } if(pre[t]!=-1) return 1; else return 0; } int Mincostmaxflow() { int maxflow=0; while(spfa()) { int Min=inf; for(int i=pre[t]; i!=-1; i=pre[edge[i^1].to]) Min=min(Min,edge[i].w-edge[i].flow); for(int i=pre[t]; i!=-1; i=pre[edge[i^1].to]) { edge[i].flow+=Min; edge[i^1].flow-=Min; ans+=Min*edge[i].cost; } maxflow+=Min; } return maxflow; } int main() { memset(head,-1,sizeof(head)); scanf("%d%d%d%d",&n,&m,&s,&t); for(int i=1; i<=m; i++) { int x,y,z,t; scanf("%d%d%d%d",&x,&y,&z,&t); add(x,y,z,t); add(y,x,0,-t); } printf("%d ",Mincostmaxflow()); printf("%d",ans); return 0; }
标签:else spfa memset cost while nod 过程 style 结束
原文地址:https://www.cnblogs.com/popo-black-cat/p/10294895.html