并不对劲的费用流

最小费用最大流肯定要保证最大流,所以它和最大流有一些类似的性质。如果把费用看成边,就可以每次走最短路(保证费用最小),走到不能走为止(保证最大流)。费用流版的ek就是这样。需要注意的是,反向弧的边权为它对应的正向弧的费用的相反数,所以最短路要用spfa来求。

费用流版的dinic,又叫zkw费用流,还是多路增广的思想。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iomanip>
#include<queue>
#define maxn 5010
#define maxm 100010
using namespace std;
int fir[maxn],nxt[maxm],v[maxm],fl[maxm],w[maxm],cnt;
int n,m,dis[maxn],s,t,inf[5],mincost,maxflow;
int p[maxn],flp[maxn],kp[maxn];
bool vis[maxn];

int read()
{
     int x = 0, f = 1;
     char c = getchar();
     while (!isdigit(c)) 
     {
         if (c == '-') f = -1;
         c = getchar();
    }
    while(isdigit(c)) x = x*10 + c - '0', c = getchar();
     return x*f;
}

void addedge(int u1,int v1,int fl1,int w1)
{
    v[cnt]=v1,w[cnt]=w1,fl[cnt]=fl1,nxt[cnt]=fir[u1],fir[u1]=cnt++;
    v[cnt]=u1,w[cnt]=-w1,fl[cnt]=0,nxt[cnt]=fir[v1],fir[v1]=cnt++;
}

bool spfa()
{
    memset(dis,0x7f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    queue<int>q;
    dis[s]=0;
    vis[s]=1;
    flp[s]=inf[0];
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        for(int k=fir[u];k!=-1;k=nxt[k])
        {
            int vv=v[k];
            if(fl[k]>0)
            {
                if(dis[vv]>dis[u]+w[k])
                {
                    dis[vv]=dis[u]+w[k];
                    if(!vis[vv])q.push(vv);
                    p[vv]=u;
                    kp[vv]=k;
                    flp[vv]=min(flp[u],fl[k]);
                    vis[vv]=1;
                }
            }
        }
        vis[u]=0;
    }
    return dis[t]==inf[0]?0:1;
}

void dfs()
{
    for(int i=t;i!=s;i=p[i])
    {
        mincost+=w[kp[i]]*flp[t];
        fl[kp[i]]-=flp[t];
        fl[kp[i]^1]+=flp[t];
    }
    maxflow+=flp[t];
    return;
}
int main()
{
    memset(fir,-1,sizeof(fir));
    memset(inf,0x7f,sizeof(inf));
    n=read(),m=read(),s=read(),t=read();
    for(int i=1;i<=m;i++)
    {
        int x=read(),y=read(),z=read(),k=read();
        addedge(x,y,z,k);
    }
    while(spfa())dfs();
    cout<<maxflow<<" "<<mincost;
}
ek
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iomanip>
#include<queue>
#define maxn 5010
#define maxm 100010
using namespace std;
int fir[maxn],nxt[maxm],v[maxm],fl[maxm],w[maxm],cnt;
int n,m,dis[maxn],s,t,inf[5],mincost,maxflow;
bool vis[maxn];
queue<int >q;
int read()
{
     int x = 0, f = 1;
     char c = getchar();
     while (!isdigit(c)) 
     {
         if (c == '-') f = -1;
         c = getchar();
    }
    while(isdigit(c)) x = x*10 + c - '0', c = getchar();
     return x*f;
}

void addedge(int u1,int v1,int fl1,int w1)
{
    v[cnt]=v1,w[cnt]=w1,fl[cnt]=fl1,nxt[cnt]=fir[u1],fir[u1]=cnt++;
    v[cnt]=u1,w[cnt]=-w1,fl[cnt]=0,nxt[cnt]=fir[v1],fir[v1]=cnt++;
}

bool spfa()
{
    memset(dis,0x7f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    dis[t]=0;
    vis[t]=1;
    q.push(t);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        for(int k=fir[u];k!=-1;k=nxt[k])
        {
            if(fl[k^1]>0)
            {
                if(dis[v[k]]>dis[u]-w[k])
                {
                    dis[v[k]]=dis[u]-w[k];
                    if(!vis[v[k]]){q.push(v[k]);}
                    vis[v[k]]=1;
                }
            }
        }
        vis[u]=0;
    }
    while(!q.empty())q.pop();
    return dis[s]==inf[0]?0:1;
}

int dfs(int u,int nowflow)
{
    if(u==t || nowflow==0)return nowflow;
    vis[u]=1;
    int sum=0,tmp;
    for(int k=fir[u];k!=-1;k=nxt[k])
    {
        if(nowflow<=0)break;
        if(fl[k]>0 && dis[v[k]]+w[k]==dis[u] && vis[v[k]]==0
        && (tmp=dfs(v[k],min(fl[k],nowflow)))>0)
        {
            nowflow-=tmp;
            sum+=tmp;
            fl[k]-=tmp;
            fl[k^1]+=tmp;
            mincost+=tmp*w[k];
        }
    }
    vis[u]=0;
    return sum;
}
int main()
{
    memset(fir,-1,sizeof(fir));
    memset(inf,0x7f,sizeof(inf));
    n=read(),m=read(),s=read(),t=read();
    for(int i=1;i<=m;i++)
    {
        int x=read(),y=read(),z=read(),k=read();
        addedge(x,y,z,k);
    }
    while(spfa())
    {
        memset(vis,0,sizeof(vis));
        maxflow+=dfs(s,inf[0]);
    }
    cout<<maxflow<<" "<<mincost;
}
dinic

 

posted @ 2018-01-19 15:34  echo6342  阅读(137)  评论(0编辑  收藏  举报