大概做法:用spfa先跑出有流最短路径,然后查询该路径的最大流,再进行修改路径上的流量,并修改反向边的,还有把费用计算起来。
注意其中的pid以及pre的作用,pre记录前导点,pid记录该点所对应的边。
然后就是这种类型题目的难点对应的应该是建图。
struct edge { int to,flow,cost,next; }; edge Grapics[Maxn<<2]; int n,m,tot,St,En; int head[maxn],pre[maxn],pid[maxn],dis[maxn]; bool vis[maxn]; void add_edge(int u,int v,int flow,int cost) { Grapics[tot].cost=cost,Grapics[tot].flow=flow,Grapics[tot].next=head[u], Grapics[tot].to=v,head[u]=tot++; Grapics[tot].cost=-cost,Grapics[tot].flow=0,Grapics[tot].next=head[v], Grapics[tot].to=u,head[v]=tot++; } void init() { memset(head,-1,sizeof(head)); tot=0,in_a=0,in_b=0; } int spfa() { memset(dis,inf,sizeof(dis)); memset(vis,0,sizeof(vis)); queue<int>que; while(!que.empty())que.pop(); que.push(St);vis[St]=1;dis[St]=0; while(!que.empty()) { int u=que.front();que.pop();vis[u]=0; for(int i=head[u];i!=-1;i=Grapics[i].next) { int v=Grapics[i].to; if(Grapics[i].flow>0&&dis[v]>dis[u]+Grapics[i].cost) { dis[v]=dis[u]+Grapics[i].cost; pre[v]=u;///存前一点 pid[v]=i;///存边 if(!vis[v]) { vis[v]=true;que.push(v); } } } } return dis[En]; } int solve() { int ans=0,tmp=0,aug=0,maxflow=0; while(1) { tmp = spfa(); if(tmp==inf)break; aug=inf;///当前路线的最大流量 for(int i=En;i!=St;i=pre[i]) aug=min(aug,Grapics[pid[i]].flow); for(int i=En;i!=St;i=pre[i]) { Grapics[pid[i]].flow-=aug; Grapics[pid[i]^1].flow+=aug; } maxflow+=aug; ans+=tmp; } return ans; }