题目链接:https://www.luogu.com.cn/problem/P3381
用SPFA求费用最短路,用pre记录路径,流量还是原来那样求。
AC代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 const int N=50005; 7 const int INF=0x3f3f3f; 8 struct node{ 9 int from,to,flow,cost,next; 10 }edge[N<<1]; 11 int head[N],pre[N],vis[N],dis[N]; 12 int tot,n,m,s,t,flow,cost; 13 void init(){ 14 memset(head,-1,sizeof(head)); 15 tot=0; 16 } 17 void add(int u,int v,int flow,int cost){ 18 edge[tot].from=u; 19 edge[tot].to=v; 20 edge[tot].flow=flow; 21 edge[tot].cost=cost; 22 edge[tot].next=head[u]; 23 head[u]=tot++; 24 25 edge[tot].from=v; 26 edge[tot].to=u; 27 edge[tot].flow=0; 28 edge[tot].cost=-cost; 29 edge[tot].next=head[v]; 30 head[v]=tot++; 31 } 32 int spfa(int s,int t){ 33 memset(dis,INF,sizeof(dis)); 34 memset(vis,0,sizeof(vis)); 35 memset(pre,-1,sizeof(pre)); 36 queue<int> q; 37 q.push(s); dis[s]=0; vis[s]=1; 38 while(!q.empty()){ 39 int u=q.front(); 40 q.pop(); vis[u]=0; 41 for(int i=head[u];i!=-1;i=edge[i].next){ 42 int v=edge[i].to; 43 if(edge[i].flow&&dis[v]>dis[u]+edge[i].cost){ 44 dis[v]=dis[u]+edge[i].cost; 45 pre[v]=i; 46 if(vis[v]==0){ 47 q.push(v); 48 vis[v]=1; 49 } 50 } 51 } 52 } 53 if(pre[t]==-1) return 0; 54 return 1; 55 } 56 void MCMF(int s,int t){ 57 cost=0,flow=0; 58 while(spfa(s,t)){ 59 int minn=INF; 60 for(int i=pre[t];i!=-1;i=pre[edge[i].from]) 61 minn=min(minn,edge[i].flow); 62 for(int i=pre[t];i!=-1;i=pre[edge[i].from]){ 63 edge[i].flow-=minn; 64 edge[i^1].flow+=minn; 65 } 66 flow+=minn; 67 cost+=minn*dis[t]; 68 } 69 } 70 int main(){ 71 init(); 72 scanf("%d%d%d%d",&n,&m,&s,&t); 73 for(int i=1;i<=m;i++){ 74 int u,v,w,f; 75 scanf("%d%d%d%d",&u,&v,&w,&f); 76 add(u,v,w,f); 77 } 78 MCMF(s,t); 79 printf("%d %d",flow,cost); 80 return 0; 81 }