【BZOJ1834】【codevs1362】网络扩容,最大流+费用流

来源:互联网 发布:淘宝店铺链接转换微信 编辑:程序博客网 时间:2024/06/05 03:56

传送门1
传送门2
写在前面:打BC被虐的好爽
思路:
第一问跑最大流即可
第二问添加带费用的边,流量为inf,继续残余网络费用流就行了,为了控制流量,让n向新的源点连一条流量为k,费用为0的边
注意:先跑最大流再加边,而且由于加两次,空间要开两倍
代码:

#include<bits/stdc++.h>#define inf 0x7fffffusing namespace std;int ans,n,m,tot=1,k,t;int up[2000],first[2000],dis[2000],cur[2000],co[40000];bool vis[2000];struct edge{    int u,v,w,cost,next;}e[80000];queue<int> q;void add(int x,int y,int z,int c){e[++tot]=(edge){x,y,z,c,first[x]};first[x]=tot;}bool bfs(){    memset(dis,0,sizeof(dis));    q.push(1);dis[1]=1;    while (!q.empty())    {        int k=q.front();q.pop();        for(int i=first[k];i;i=e[i].next)            if (!dis[e[i].v]&&e[i].w)                dis[e[i].v]=dis[k]+1,q.push(e[i].v);    }    if (dis[n])        for (int i=1;i<=n;i++) cur[i]=first[i];    return dis[n];}int dfs(int x,int maxn){    if (x==n) return maxn;    int used=0;    for (int i=cur[x];i;i=e[i].next)        if (dis[e[i].v]==dis[x]+1)        {            int k=dfs(e[i].v,min(maxn,e[i].w));            e[i].w-=k;e[i^1].w+=k;            if (e[i].w) cur[x]=i;            used+=k;            if (used==maxn) return maxn;        }    if (!used) dis[x]=0;    return used;}bool spfa(){    memset(dis,63,sizeof(dis));    dis[1]=0;q.push(1);    while (!q.empty())    {        int k=q.front();q.pop();vis[k]=0;        for (int i=first[k];i;i=e[i].next)            if (e[i].w&&dis[e[i].v]>dis[k]+e[i].cost)            {                up[e[i].v]=i;                dis[e[i].v]=dis[k]+e[i].cost;                if (!vis[e[i].v]) vis[e[i].v]=1,q.push(e[i].v);            }    }    return dis[t]<inf;}void flow(){    int minn=inf;    for (int i=up[t];i;i=up[e[i].u]) minn=min(minn,e[i].w);    for (int i=up[t];i;i=up[e[i].u])        ans+=minn*e[i].cost,        e[i].w-=minn,e[i^1].w+=minn;}main(){    int x,y,z,c;    scanf("%d%d%d",&n,&m,&k);    for (int i=1;i<=m;i++)        scanf("%d%d%d%d",&x,&y,&z,&c),        add(x,y,z,0),        co[tot]=c,        add(y,x,0,0);    while (bfs()) ans+=dfs(1,inf);    printf("%d",ans);    ans=0;int lim=tot;    for (int i=2;i<=lim;i+=2)        add(e[i].u,e[i].v,inf,co[i]),        add(e[i].v,e[i].u,0,-co[i]);    add(n,t,k,0);add(t,n,0,0);    while (spfa()) flow();    printf(" %d",ans);}
0 0
原创粉丝点击