【[ZJOI2010]网络扩容】

题目

第一问直接板子敲上去

第二问并不明白直接在残量网络上加边的神仙做法

非常显然我们需要让流量加\(k\),那么我们就使得网络里的总流量为\(maxf+k\)\(maxf\)是第一问求出来的最大流

所以搞一个超级源点,向\(1\)连一条流量是\(maxf+k\)费用是\(0\)的边,之后在原来的图的基础上再给每条边加一条流量为\(inf\),费用为相应费用的边

这样让它自己在里面流就必然会流出来\(maxf+k\)的流量

求出最小费用就好了

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define maxn 1005
#define re register
#define LL long long
#define inf 999999999
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read()
{
    char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();
    return x;
}
struct E{int v,nxt,w,f;} e[20005];
int d[maxn],vis[maxn],head[maxn];
int n,m,num=1,K,S,T;
int a[5005],b[5005],c[5005],t[5005];
inline void add(int x,int y,int ca,int z){e[++num].v=y;e[num].nxt=head[x];e[num].f=ca,e[num].w=z;head[x]=num;}
inline void C(int x,int y,int ca,int z){add(x,y,ca,z),add(y,x,0,-1*z);}
inline int SPFA()
{
    std::queue<int> q;
    for(re int i=S;i<=T;i++) d[i]=inf,vis[i]=0;
    d[T]=0,vis[T]=1,q.push(T);
    while(!q.empty())
    {
        int k=q.front();q.pop();vis[k]=0;
        for(re int i=head[k];i;i=e[i].nxt)
        if(e[i^1].f&&d[e[i].v]>d[k]+e[i^1].w)
        {
            d[e[i].v]=d[k]+e[i^1].w;
            if(!vis[e[i].v]) vis[e[i].v]=1,q.push(e[i].v);
        }
    }
    return d[S]<inf;
}
int dfs(int x,int now)
{
    if(x==n||!now) return now;
    int flow=0,ff;vis[x]=1;
    for(re int i=head[x];i;i=e[i].nxt)
    if(e[i].f&&!vis[e[i].v]&&d[e[i].v]==d[x]+e[i^1].w)
    {
        ff=dfs(e[i].v,min(e[i].f,now));
        if(ff<=0) continue;
        now-=ff,flow+=ff;
        e[i].f-=ff,e[i^1].f+=ff;
        if(!now) break;
    }
    return flow;
}
int main()
{
    n=read(),m=read(),K=read();S=1,T=n;
    int x,y,ca,z,ans=0,tot=0,Mf=0;
    for(re int i=1;i<=m;i++) 
        x=read(),y=read(),ca=read(),z=read(),C(x,y,ca,0),a[i]=x,b[i]=y,c[i]=ca,t[i]=z;
    while(SPFA())
    {
        vis[T]=1;
        while(vis[T]) 
        {
            for(re int i=S;i<=T;i++) vis[i]=0;
            int F=dfs(S,inf);
            ans+=F;
        }
    }
    printf("%d ",ans);
    num=1,memset(head,0,sizeof(head)),memset(e,0,sizeof(e));
    for(re int i=1;i<=m;i++) C(a[i],b[i],inf,t[i]),C(a[i],b[i],c[i],0);
    S=0,C(S,1,ans+K,0);ans=0;
    while(SPFA())
    {
        vis[T]=1;
        while(vis[T]) 
        {
            for(re int i=S;i<=T;i++) vis[i]=0;
            int F=dfs(S,inf);
            ans+=F*d[S];
        }
    }
    printf("%d\n",ans);
    return 0;
}
posted @ 2019-01-17 13:08  asuldb  阅读(101)  评论(0编辑  收藏  举报