UVa10594 Data Flow

        题意:网络中传送数据量为D的数据,每条边容量为K,需要花一定的时间。问传送完数据花费的最少时间。

        思路:最小费用最大流。为了控制流量,除了输入描述的图外,加上一条边,即真正的源到输入的源,其容量为数据量。需要注意时间比较大,得用long long;图中的边是双向的,但是两个相反的方向不能认为互为逆向边,需要加入逆向的负权边,不过我实现的时候没加,用了当前流量判断时间应该是正还是负。


#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <ctype.h>
#define INF 10000000000000000ll
using namespace std;

int N,M;
long long cost[110][110];
long long c[110][110];
long long f[110][110];

int main(){
	while(cin>>N>>M){
		memset(cost,0,sizeof(cost));
		memset(c,0,sizeof(c));
		memset(f,0,sizeof(f));
		
		
		int u,v,w;
		for(int i=1;i<=M;i++){
			cin>>u>>v>>w;
			cost[u][v]=cost[v][u]=w;
			c[u][v]=c[v][u]=1;
		}
		int D,K;
		cin>>D>>K;
		for(int i=1;i<=N;i++){
			for(int j=1;j<=N;j++){
				if(c[i][j])c[i][j]=K;
			}
		}
		
		c[0][1]=c[1][0]=D;
		
		bool inq[110]; 
		int pre[110];
		long long a[110];
		long long b[110];
		long long maxf=0;
		long long minc=0;
		
		while(true){
			memset(a,0,sizeof(a));
			a[0]=INF;
			for(int i=1;i<=N;i++)b[i]=INF;
			b[0]=0;
			memset(inq,0,sizeof(inq));
			queue<int> que;
			que.push(0);
			
			while(!que.empty()){
				int cur=que.front();que.pop();inq[cur]=false;
				for(int i=0;i<=N;i++){
					if(f[cur][i]>=0){
						if( (b[cur]+cost[cur][i]<b[i])&&(c[cur][i]-f[cur][i])>0 ){
							if(!inq[i]){
								inq[i]=true;
								que.push(i);
							}
							long long t=min(a[cur],c[cur][i]-f[cur][i]);
							pre[i]=cur;
							b[i]=b[cur]+cost[cur][i];
							a[i]=t;
						}
					}else{
						if( (b[cur]-cost[cur][i]<b[i])&&(c[cur][i]-f[cur][i])>0 ){
							if(!inq[i]){
								inq[i]=true;
								que.push(i);
							}
							long long t=min(a[cur],c[cur][i]-f[cur][i]);
							pre[i]=cur;
							b[i]=b[cur]-cost[cur][i];
							a[i]=t;
						}
					}
				}
			}
			
			if(!a[N])break;
			maxf+=a[N];
			minc+=b[N]*a[N];
			
			for(int i=N;i!=0;i=pre[i]){
				f[pre[i]][i]+=a[N];
				f[i][pre[i]]-=a[N];
			}
			
		}
		if(maxf==D){
			cout<<minc<<endl;
		}else{
			cout<<"Impossible."<<endl;
		}
		
	}
	return 0;
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值