洛谷3381

最小费用最大流模板题

思路和网络流的EK算法类似,

1.建正向边,反向边(反向边流量为0,花费为负数:走反向边即取消上次走过后增加的值,因此如此定义)

2.用spfa增广,找到流量大于0且由花费决定的最小dis[ t ],接着回溯,找到能通过的最大流量(minn)

3.ansflow+=minn;anscost+=minn*dis[t];

4.重复2.3步骤,直至无法增广,即为答案

#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define INF 0x33333333
using namespace std;
const int N=5002,M=50002;
int n,m,s,t,cnt=-1,vis[N],dis[N],head[N];
int pv[N],pe[N];
struct data{int v,flow,cos,next;}edge[2*M];
queue<int>q;

inline void read(int &x){
    char ch=getchar();x=0;
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
}

inline bool spfa(int S,int T)
{
    memset(dis,0x33,sizeof dis);
    memset(vis,0,sizeof vis);
    q.push(S),vis[S]=1,dis[S]=0;
    while(!q.empty())
    {
        int now=q.front();q.pop();vis[now]=0;
        for (int i=head[now];~i;i=edge[i].next)//注意不是i>0;会出现第0条边 
            if (edge[i].flow>0 && dis[edge[i].v]>dis[now]+edge[i].cos)
            {
                dis[edge[i].v]=dis[now]+edge[i].cos;
                pe[edge[i].v]=i,pv[edge[i].v]=now;
                if (!vis[edge[i].v])
                    vis[edge[i].v]=1,q.push(edge[i].v);
            }
    }
    return dis[T]<INF;
}

inline void Putans(int x){
    if(x>=10)Putans(x/10);putchar(x%10+'0');
}

inline void mfmc(int S,int T){
    int Cos=0,Flow=0,minn;
    while(spfa(S,T)){
        minn=INF;
        for(int i=T;i!=S;i=pv[i])minn=min(minn,edge[pe[i]].flow);
        Cos+=minn*dis[T];
        Flow=Flow+minn;
        for(int i=T;i!=S;i=pv[i]){edge[pe[i]].flow-=minn;edge[pe[i]^1].flow+=minn;}
    }
    Putans(Flow);printf(" ");Putans(Cos);//printf("%d %d",Flow,Cos);
}

inline void insert(int u,int v,int flow,int cost){
    edge[++cnt].v=v;
    edge[cnt].flow=flow;edge[cnt].cos=cost;edge[cnt].next=head[u];head[u]=cnt;
}

int main(){
    read(n);read(m);read(s);read(t);
    memset(head,-1,sizeof(head));//一定要赋值-1,否则spfa时出现第0条边,无限循环 
    memset(edge,-1,sizeof(edge));
    for(int i=1;i<=m;i++){//tot初值为-1(保证 ^1后是反向边) 
        int u,v,flow,cost;
        read(u);read(v);read(flow);read(cost);
        insert(u,v,flow,cost);insert(v,u,0,-cost);//flow要赋值0,否则其初值为-1  
    }
    mfmc(s,t);
}

 

posted @ 2018-04-20 09:33  lnyzo  阅读(122)  评论(0编辑  收藏  举报