zoukankan      html  css  js  c++  java
  • [ZJOI2010]网络扩容

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

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

    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


    费用流板子题吧……建费用为0,流量为C的边,和费用为W,流量为inf的边,直接跑费用流即可

    /*program from Wolfycz*/
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define inf 0x7f7f7f7f
    typedef long long ll;
    typedef unsigned int ui;
    typedef unsigned long long ull;
    template<typename T>T min(T x,T y){return x<y?x:y;}
    template<typename T>T max(T x,T y){return x>y?x:y;}
    inline char gc(){
    	static char buf[1000000],*p1=buf,*p2=buf;
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
    }
    template<typename T>inline T frd(T x){
    	int f=1; char ch=gc();
    	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')    f=-1;
    	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    template<typename T>inline T read(T x){
    	int f=1;char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x<0)    putchar('-'),x=-x;
    	if (x>9)	print(x/10);
    	putchar(x%10+'0');
    }
    const int N=1e3,M=2e4;
    int pre[M+10],now[N+10],child[M+10],val[M+10],cost[M+10],tot=1;
    int dis[N+10],deep[N+10],S,T;
    void join(int x,int y,int v,int w){pre[++tot]=now[x],now[x]=tot,child[tot]=y,val[tot]=v,cost[tot]=w;}
    void insert(int x,int y,int v,int w){join(x,y,v,w),join(y,x,0,-w);}
    bool SPFA(){
    	static int h[N+10];
    	static bool vis[N+10];
    	int head=0,tail=1;
    	memset(dis,63,sizeof(dis));
    	memset(deep,255,sizeof(deep));
    	h[1]=S,dis[S]=0;
    	while (head!=tail){
    		if (++head>N)	head=1;
    		int Now=h[head];
    		for (int p=now[Now],son=child[p];p;p=pre[p],son=child[p]){
    			if (val[p]&&dis[son]>dis[Now]+cost[p]){
    				deep[son]=deep[Now]+1;
    				dis[son]=dis[Now]+cost[p];
    				if (!vis[son]){
    					if (++tail>N)	tail=1;
    					vis[h[tail]=son]=1;
    				}
    			}
    		}
    		vis[Now]=0;
    	}
    	return ~deep[T];
    }
    int Dinic(int x,int v){
    	if (x==T)	return v;
    	int res=0;
    	for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
    		if (val[p]&&dis[son]==dis[x]+cost[p]&&deep[son]>deep[x]){
    			int k=Dinic(son,min(v,val[p]));
    			v-=k,val[p]-=k;
    			res+=k,val[p^1]+=k;
    			if (!v)	break;
    		}
    	}
    	if (!res)	deep[x]=-1;
    	return res;
    }
    void MCMF(int K){
    	int MaxFlow=0,MinCost=0; bool put=0;
    	while (SPFA()){
    		if (dis[T]>0&&!put){
    			printf("%d ",MaxFlow);
    			put=1,MaxFlow=0;
    		}
    		int tmp=Dinic(S,inf);
    		if (put&&K<=MaxFlow+tmp){
    			MinCost+=(K-MaxFlow)*dis[T];
    			printf("%d
    ",MinCost);
    			return;
    		}
    		MaxFlow+=tmp;
    		MinCost+=tmp*dis[T];
    	}
    }
    int main(){
    	int n=read(0),m=read(0),K=read(0); S=1,T=n;
    	for (int i=1;i<=m;i++){
    		int x=read(0),y=read(0),v=read(0),w=read(0);
    		insert(x,y,v,0);
    		insert(x,y,inf,w);
    	}
    	MCMF(K);
    	return 0;
    }
    
  • 相关阅读:
    LeetCode12: 整数转罗马数字
    LeetCode11:盛最多水的容器
    LeetCode09:判断回文数
    LeetCode08:字符串转换成整数
    LeetCode04:寻找中位数
    LeetCode03:无重复字符的最长子串
    《JAVA编程思想》第四版 PDF 下载 中文版和英文版 高清PDF扫描带书签
    XML
    异常
    委托和匿名方法和Lambda表达式
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/10629015.html
Copyright © 2011-2022 走看看