网络流--费用流

具体说就是每条管道都有一个cost,要你在最大流情况下使总流量最小.
算法:
十分暴力,spfa跑能否增广同时每次走cost最小的路(就是最短路..),然后增广..

#include
using namespace std;
int n,m,s,t,to[100010],las[100010],head[5010],next[100010],pre[5010],cost[100010],dis[5010],num;bool inq[5010];
void read(int &x)
{
    char c=getchar();x=0;int r=1;
    while(c>'9'||c<'0')
    {if(c=='-')r=-1;c=getchar();}
    while(c<='9'&&c>='0')x=(x<<3)+(x<<1)+c-48,c=getchar();
    x*=r;
}
void init()
{
    memset(head,-1,sizeof head),
    memset(next,-1,sizeof next),
    num=-1;
}
void add_edge(int u,int v,int w,int f)
{
    next[++num]=head[u],to[num]=v,
    las[num]=w,cost[num]=f,head[u]=num;
}
bool spfa()
{
    memset(inq,0,sizeof inq),
    memset(pre,-1,sizeof pre),
    memset(dis,127,sizeof dis);
    queue<int>q;int nw,v;
    dis[s]=0,inq[s]=1,q.push(s);
    while(!q.empty())
    {
        nw=q.front(),q.pop(),inq[nw]=0;
        for(int i=head[nw];i!=-1;i=next[i])
        {
            v=to[i];
            if(las[i]!=0&&dis[v]>dis[nw]+cost[i])
            {
                dis[v]=dis[nw]+cost[i];
                pre[v]=i;if(!inq[v])q.push(v);inq[v]=1;
            }
        }   
    }
    return dis[t]<=1e9;
}
void mcmf()
{
    int flow=0,nw=0,spd=0;
    while(spfa())
    {
        nw=1e9;
        for(int i=pre[t];i!=-1;i=pre[to[i^1]])nw=min(nw,las[i]);
        for(int i=pre[t];i!=-1;i=pre[to[i^1]])las[i]-=nw,las[i^1]+=nw;
        flow+=nw;spd+=nw*dis[t];
    }
    printf("%d %d",flow,spd);
}
int main()
{
    init();int u,v,w,f;
    read(n),read(m),read(s),read(t);
    for(int i=1;i<=m;i++)
    {
        read(u),read(v),read(w),read(f);
        add_edge(u,v,w,f),add_edge(v,u,0,-f);
    }
    mcmf();
    return 0;
}

你可能感兴趣的:(训练集)