最小费用最大流板子(转载)

先贴学习博客:博客

遇到的题目:题目链接

牛客练习赛65

E-游走配对

官方题解:

感觉很少遇到最小费用最大流题,可能以前遇到过,只是水平不够  没看到那题,现在看到了就顺手补补吧。

今天先贴板子,先学会怎么用 以后有时间再学,写个博客插个眼。

最小费用最大流模版.求最大费用最大流建图时把费用取负即可。

作者:kkksx
链接:https://ac.nowcoder.com/discuss/439404?type=101&order=0&pos=2&page=1&channel=1004&source_id=discuss_tag
来源:牛客网

#include<bits/stdc++.h>
#define N 405
#define M 200005
using namespace std;
int n,m,q,s,t;
int in[N],out[N],a[N],b[N];
int dis[N],flow[N],exist[N];
int pre[N],preedge[N];
 
struct Edge
{
    int next,to,flow,dis;
}edge[M << 1]; int head[N],cnt = 1;
void add_edge(int from,int to,int flow,int dis)
{
    edge[++cnt].next = head[from];
    edge[cnt].to = to;
    edge[cnt].flow = flow;
    edge[cnt].dis = dis;
    head[from] = cnt;
}
void add(int from,int to,int flow,int dis)
{
    add_edge(from,to,flow,dis);
    add_edge(to,from,0,-dis);
}
 
bool spfa(int s,int t)
{
    memset(dis,100,sizeof(dis));
    memset(flow,100,sizeof(flow));
    memset(exist,0,sizeof(exist));
    queue<int> q;
    pre[t]=-1; exist[s]=1; dis[s]=0; q.push(s);
    while(!q.empty())
    {
        int u=q.front();q.pop();exist[u]=0;
        for(int i=head[u];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(edge[i].flow>0&&dis[v]>dis[u]+edge[i].dis)
            {
                dis[v]=dis[u]+edge[i].dis;
                flow[v]=min(edge[i].flow,flow[u]);
                pre[v]=u;
                preedge[v]=i;
                if(!exist[v])
                {
                    exist[v]=1;
                    q.push(v);
                }
            }
        }
    }
    return pre[t]!=-1;
}
int MCMF()
{
    int ret = 0;
    while(spfa(s,t))
    {
        ret += flow[t] * dis[t];
        int now = t;
        while(now!=s)
        {
            edge[preedge[now]].flow -= flow[t];
            edge[preedge[now]^1].flow += flow[t];
            now=pre[now];
        }
    }
    return ret;
}
 
int main()
{
//    freopen("9.in","r",stdin);
//    freopen("e9.out","w",stdout);
    scanf("%d%d%d",&n,&m,&q);
    s = 0,t = N - 1;
    for(int i=1;i<=n;++i)
    {
        int a,b; scanf("%d%d",&a,&b);
        for(int j=1;j<=q * 2;++j) add(i,i + n,1,a + (j - 1) * b);
    }
    for(int i=1;i<=m;++i)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        add(x + n,y,q * 2,0);
        add(y + n,x,q * 2,0);
    }
    for(int i=1;i<=q;++i)
    {
        int x; scanf("%d",&x);
        add(s,x,1,0);
    }
    for(int i=1;i<=q;++i)
    {
        int x; scanf("%d",&x);
        add(x + n,t,1,0);
    }
    printf("%d\n",MCMF());
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41286356/article/details/106911621