最小费用最大流
大概做法:用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;
}
more crazy more get!
浙公网安备 33010602011771号