zoukankan      html  css  js  c++  java
  • 【BZOJ】1834 [ZJOI2010]network 网络扩容

    【算法】网络流-最大流+最小费用最大流(费用流)

    【题解】

    第一问跑最大流。

    第二问:

    原始边相当于费用为0的边,再原图(跑过最大流的图)基础上添加带费用的边,容量为k(相当于inf)。

    第一问最大流使用了哪条边对第二问没有影响,因为费用流肯定优先往费用为0的边(原始边)跑。

    限流k?添加超级源向1连容量k费用0的边即可。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=1010,maxm=10010,N=1005,inf=0x3f3f3f3f;
    int tot=1,first[maxn],d[maxn],q[maxn],cur[maxn],S,T,sum,n,m,K,u[maxm],v[maxm],w[maxm];
    bool vis[maxn];
    struct edge{int v,f,c,from;}e[maxm*2];
    
    void insert(int u,int v,int f,int c){
        tot++;e[tot].v=v;e[tot].f=f;e[tot].c=c;e[tot].from=first[u];first[u]=tot;
        tot++;e[tot].v=u;e[tot].f=0;e[tot].c=-c;e[tot].from=first[v];first[v]=tot;
    }
    bool bfs(){
        memset(d,-1,sizeof(d));
        int head=0,tail=1;q[head]=S;d[S]=0;
        while(head<tail){
            int x=q[head++];
            for(int i=first[x];i;i=e[i].from)
            if(e[i].f&&d[e[i].v]==-1){
                d[e[i].v]=d[x]+1;
                q[tail++]=e[i].v;
            }
        }
        return ~d[T];
    }
    int dinic(int x,int a){
        if(x==T||a==0)return a;
        int flow=0,f;
        for(int& i=cur[x];i;i=e[i].from)
        if(d[e[i].v]==d[x]+1&&(f=dinic(e[i].v,min(e[i].f,a)))){
            e[i].f-=f;e[i^1].f+=f;
            flow+=f;a-=f;
            if(a==0)break;
        }
        return flow;
    }
    int solve1(){
        int ans=0;
        while(bfs()){
            for(int i=S;i<=T;i++)cur[i]=first[i];
            ans+=dinic(S,inf);
        }
        return ans;
    }
    bool spfa(){
        memset(d,0x3f,sizeof(d));
        int head=0,tail=1;q[head]=T;d[T]=0;vis[T]=1;
        while(head!=tail){
            int x=q[head++];if(head>N)head=0;
            for(int i=first[x];i;i=e[i].from)
            if(e[i^1].f&&d[x]+e[i^1].c<d[e[i].v]){
                d[e[i].v]=d[x]+e[i^1].c;
                if(!vis[e[i].v]){
                    if(d[e[i].v]<d[q[head]]){if(--head<0)head=N;q[head]=e[i].v;}
                    else{q[tail++]=e[i].v;if(tail>N)tail=0;}
                    vis[e[i].v]=1;
                }
            }
            vis[x]=0;//
        }
        return d[S]<inf;
    }
    int dfs(int x,int a){
        if(x==T||a==0)return a;
        vis[x]=1;
        int flow=0,f;
        for(int& i=cur[x];i;i=e[i].from)
        if(!vis[e[i].v]&&d[e[i].v]+e[i].c==d[x]&&(f=dfs(e[i].v,min(e[i].f,a)))){
            e[i].f-=f;e[i^1].f+=f;
            sum+=e[i].c*f;
            flow+=f;a-=f;
            if(a==0)break;
        }
        vis[x]=0;
        return flow;
    }
    int solve2(){
        sum=0;
        while(spfa()){
            for(int i=S;i<=T;i++)cur[i]=first[i];
            dfs(S,inf);
        }
        return sum;
    }
    int main(){
        scanf("%d%d%d",&n,&m,&K);
        S=1;T=n;
        for(int i=1;i<=m;i++){
            int c;
            scanf("%d%d%d%d",&u[i],&v[i],&c,&w[i]);
            insert(u[i],v[i],c,0);
        }
        printf("%d ",solve1());
        S=0;
        for(int i=1;i<=m;i++)insert(u[i],v[i],K,w[i]);
        insert(S,1,K,0);
        printf("%d",solve2());
        return 0;
    }
    View Code
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=1010,maxm=10010,N=1005,inf=0x3f3f3f3f;
    int tot=1,first[maxn],d[maxn],q[maxn],cur[maxn],S,T,sum,n,m,K,u[maxm],v[maxm],w[maxm],c[maxm];
    bool vis[maxn];
    struct edge{int v,f,c,from;}e[maxm*2];
    
    void insert(int u,int v,int f,int c){
        tot++;e[tot].v=v;e[tot].f=f;e[tot].c=c;e[tot].from=first[u];first[u]=tot;
        tot++;e[tot].v=u;e[tot].f=0;e[tot].c=-c;e[tot].from=first[v];first[v]=tot;
    }
    bool bfs(){
        memset(d,-1,sizeof(d));
        int head=0,tail=1;q[head]=S;d[S]=0;
        while(head<tail){
            int x=q[head++];
            for(int i=first[x];i;i=e[i].from)
            if(e[i].f&&d[e[i].v]==-1){
                d[e[i].v]=d[x]+1;
                q[tail++]=e[i].v;
            }
        }
        return ~d[T];
    }
    int dinic(int x,int a){
        if(x==T||a==0)return a;
        int flow=0,f;
        for(int& i=cur[x];i;i=e[i].from)
        if(d[e[i].v]==d[x]+1&&(f=dinic(e[i].v,min(e[i].f,a)))){
            e[i].f-=f;e[i^1].f+=f;
            flow+=f;a-=f;
            if(a==0)break;
        }
        return flow;
    }
    int solve1(){
        int ans=0;
        while(bfs()){
            for(int i=S;i<=T;i++)cur[i]=first[i];
            ans+=dinic(S,inf);
        }
        return ans;
    }
    bool spfa(){
        memset(d,0x3f,sizeof(d));
        int head=0,tail=1;q[head]=T;d[T]=0;vis[T]=1;
        while(head!=tail){
            int x=q[head++];if(head>N)head=0;
            for(int i=first[x];i;i=e[i].from)
            if(e[i^1].f&&d[x]+e[i^1].c<d[e[i].v]){
                d[e[i].v]=d[x]+e[i^1].c;
                if(!vis[e[i].v]){
                    if(d[e[i].v]<d[q[head]]){if(--head<0)head=N;q[head]=e[i].v;}
                    else{q[tail++]=e[i].v;if(tail>N)tail=0;}
                    vis[e[i].v]=1;
                }
            }
            vis[x]=0;//
        }
        return d[S]<inf;
    }
    int dfs(int x,int a){
        if(x==T||a==0)return a;
        vis[x]=1;
        int flow=0,f;
        for(int& i=cur[x];i;i=e[i].from)
        if(!vis[e[i].v]&&d[e[i].v]+e[i].c==d[x]&&(f=dfs(e[i].v,min(e[i].f,a)))){
            e[i].f-=f;e[i^1].f+=f;
            sum+=e[i].c*f;
            flow+=f;a-=f;
            if(a==0)break;
        }
        vis[x]=0;
        return flow;
    }
    int solve2(){
        sum=0;
        while(spfa()){
            for(int i=S;i<=T;i++)cur[i]=first[i];
            dfs(S,inf);
        }
        return sum;
    }
    int main(){
        scanf("%d%d%d",&n,&m,&K);
        S=1;T=n;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d%d",&u[i],&v[i],&c[i],&w[i]);
            insert(u[i],v[i],c[i],0);
        }
        int now=0;
        printf("%d ",now=solve1());
        tot=1;memset(first,0,sizeof(first));//
        for(int i=1;i<=m;i++){
            insert(u[i],v[i],c[i],0);
            insert(u[i],v[i],K,w[i]);
        }
        S=0;
        insert(S,1,now+K,0);
        printf("%d",solve2());
        return 0;
    }
    View Code
  • 相关阅读:
    用Doxygen生成X3D的继承关系树
    FreeBSD 8.0候选版本RC2发布
    Mozilla Firefox, Apple Safari,Chrome等主流浏览器均开始WebGL支持
    关于企业管理信息系统
    [转]WebGL标准最新进展
    C++ + Irrlicht整一个东东?
    FreeWRL Windows Beta版本注记
    选择C++开发环境
    老人与老浏览器-李开复与成熟度最高的VRML浏览器SGI Cosmo
    WebGL概念及HTML5推广给X3D规范带来的新出路
  • 原文地址:https://www.cnblogs.com/onioncyc/p/6486842.html
Copyright © 2011-2022 走看看