zoukankan      html  css  js  c++  java
  • 【BZOJ1834】网络扩容(最大流,费用流)

    【BZOJ1834】网络扩容(最大流,费用流)

    题面

    Description

    给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求: 1、 在不扩容的情况下,1到N的最大流; 2、 将1到N的最大流增加K所需的最小扩容费用。

    Input

    输入文件的第一行包含三个整数N,M,K,表示有向图的点数、边数以及所需要增加的流量。 接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边。

    Output

    输出文件一行包含两个整数,分别表示问题1和问题2的答案。

    Sample Input

    5 8 2

    1 2 5 8

    2 5 9 9

    5 1 6 2

    5 1 1 8

    1 2 8 7

    2 5 4 9

    1 2 1 1

    1 4 2 1

    Sample Output

    13 19

    30%的数据中,N<=100

    100%的数据中,N<=1000,M<=5000,K<=10

    题解

    第一问裸的最大流
    第二问
    把原来的边的费用视为0
    扩容的话就额外连一条容量为INF,费用为W的边
    因为限制K流量
    S向1连容量为K,费用为0的边
    其实没必要把图推到重建
    原来跑最大流的时候就流满了流了
    反正费用都是0,与第二问不影响
    直接加边就行了

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define MAXL 1000000
    #define MAX 100000
    #define INF 1000000000
    inline int read()
    {
        int x=0,t=1;char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        if(ch=='-')t=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
        return x*t;
    }
    struct Line
    {
        int v,next,w,fy;
    }e[MAXL];
    int U[MAX],V[MAX],C[MAX],W[MAX];
    int h[MAX],cnt;
    int ans,S,T,n,m;
    inline void Add(int u,int v,int w,int fy)
    {
        e[cnt]=(Line){v,h[u],w,fy};
        h[u]=cnt++;
        e[cnt]=(Line){u,h[v],0,-fy};
        h[v]=cnt++;
    }
    int level[MAX];
    bool BFS()
    {
        memset(level,0,sizeof(level));
        level[S]=1;
        queue<int> Q;
        Q.push(S);
        while(!Q.empty())
        {
            int u=Q.front();Q.pop();
            for(int i=h[u];i!=-1;i=e[i].next)
            {
                int v=e[i].v;
                if(e[i].w&&!level[v])
                    level[v]=level[u]+1,Q.push(v);
            }
        }
        return level[T];
    }
    int DFS(int u,int flow)
    {
        if(flow==0||u==T)return flow;
        int ret=0;
        for(int i=h[u];i!=-1;i=e[i].next)
        {
            int v=e[i].v;
            if(e[i].w&&level[v]==level[u]+1)
            {
                int dd=DFS(v,min(flow,e[i].w));
                flow-=dd;ret+=dd;
                e[i].w-=dd;e[i^1].w+=dd;
            }
        }
        return ret;
    }
    int Dinic()
    {
        int ret=0;
        while(BFS())ret+=DFS(S,INF);
        return ret;
    }
    bool vis[MAX];
    int dis[MAX],pe[MAX],pr[MAX],Cost;
    int K;
    bool SPFA()
    {
    	for(int i=1;i<=T;++i)dis[i]=INF;
    	queue<int> Q;Q.push(S);
    	while(!Q.empty())
    	{
    		int u=Q.front();Q.pop();
    		for(int i=h[u];i!=-1;i=e[i].next)
    		{
    			int v=e[i].v;
    			if(e[i].w&&dis[v]>dis[u]+e[i].fy)
    			{
    				dis[v]=dis[u]+e[i].fy;
    				pe[v]=i;pr[v]=u;
    				if(!vis[v])vis[v]=true,Q.push(v);
    			}
    		}
    		vis[u]=false;
    	}
    	if(dis[T]==INF)return false;
    	int flow=INF;
    	for(int i=T;i!=S;i=pr[i])flow=min(flow,e[pe[i]].w);
    	for(int i=T;i!=S;i=pr[i])e[pe[i]].w-=flow,e[pe[i]^1].w+=flow;
    	Cost+=flow*dis[T];
    	return true;
    }
    int main()
    {
    	memset(h,-1,sizeof(h));
    	n=read();m=read();K=read();
    	S=1;T=n;
    	for(int i=1;i<=m;++i)
    	{
    		U[i]=read();V[i]=read();C[i]=read();W[i]=read();
    		Add(U[i],V[i],C[i],0);
    	}
    	int G;
    	printf("%d ",G=Dinic());
    	S=0;T=n;Add(S,1,K,0);
    	for(int i=1;i<=m;++i)Add(U[i],V[i],K,W[i]);
    	while(SPFA());
    	printf("%d
    ",Cost);
    	return 0;
    }
    
    
  • 相关阅读:
    Android上传图片到PHP服务器并且支持浏览器上传文件(word、图片、音乐等)
    Android+PHP服务器+MySQL实现安卓端的登录
    Win7重装系统遇到的问题以及MysQL的问题解决
    PHP学习之登录以及后台商品展示
    PHP学习之输出语句、注释、算数运算符
    利用Dreamweaver配置PHP服务器的站点
    WAMP集成环境的安装
    暑假计划
    Android提交数据到JavaWeb服务器实现登录
    Android之滑屏动画和自定义控件
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8143339.html
Copyright © 2011-2022 走看看