UVA - 10594 Data Flow (最小费用最大流)

题目大意:
在无向图G中把D单位的数据从1号点传到N号点,每条边允许传输数据的最大容量均为K,给出每条边传输单位数据的费用,求最小传输D单位数据的费用。

解析:
注意是无向图,必然要用邻接表,将无向边分成两个方向的有向边。1为源点,N为汇点,求流量为D的最小费用,因为费用为D,则用0到1的容量为D,表示初始的费用。

然后套模板,求出0~n的最小费用。

总结:照着模板敲代码,我都能敲错,看来我真的是太粗心了。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn = 105;
struct Edge {
	int from,to,cap,flow,cost;
	Edge(int u,int v,int c,int f,ll w) {
		from = u;
		to = v;
		cap = c;
		flow = f;
		cost = w;
	}
};
struct MCMF {
	int n, m;
	vector<Edge> edges;
	vector<int> G[maxn];
	int inq[maxn];
	int d[maxn];
	int p[maxn];
	int a[maxn];

	void init(int n) {
		this->n = n;
		for(int i = 0; i < n; i++) {
			G[i].clear();
		}
		edges.clear();
	}
	void addEdge(int from,int to,int cap,ll cost) {
		edges.push_back(Edge(from,to,cap,0,cost));
		edges.push_back(Edge(to,from,0,0,-cost));
		m = edges.size();
		G[from].push_back(m-2);
		G[to].push_back(m-1);
	}
	bool BellmanFord(int s,int t,int &flow,ll &cost) {
		memset(d,0,sizeof(d));
		for(int i = 0; i < n; i++) {
			d[i] = INF;
		}
		memset(inq,0,sizeof(inq));
		d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF;
		
		queue<int> que;
		que.push(s);
		while(!que.empty()) {
			int u = que.front();
			que.pop();
			inq[u] = false;
			for(int i = 0; i < G[u].size(); i++) {
				Edge& e = edges[G[u][i]];
				if(e.cap > e.flow && d[e.to] > d[u] + e.cost) {
					d[e.to] = d[u] + e.cost;
					p[e.to] = G[u][i];
					a[e.to] = min(a[u], e.cap - e.flow);
					if(!inq[e.to]) {
						que.push(e.to);
						inq[e.to] = true;
					}
				}
			}
		}
		if(d[t] == INF) {
			return false;
		}
		flow += a[t];
		cost += (ll)d[t] * (ll)a[t];
		for(int u = t; u != s; u = edges[p[u]].from) {
			edges[p[u]].flow += a[t];
			edges[p[u]^1].flow -= a[t];
		}
		return true;
	}
	int MincostMaxflow(int s,int t,ll& cost) {
		int flow = 0;
		cost = 0;
		while(BellmanFord(s,t,flow,cost));
		return flow;
	}
};

struct Node {
	int u,v,w;
}e[5005];

int main() {
	int n,m;
	ll D,K;
	MCMF mcmf;
	while(scanf("%d%d",&n,&m) != EOF) {
		mcmf.init(n+1);
		for(int i = 0; i < m; i++) {
			scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
		}
		scanf("%lld%lld",&D,&K);
		mcmf.addEdge(0,1,D,0);
		for(int i = 0; i < m; i++) {
			mcmf.addEdge(e[i].u,e[i].v,K,e[i].w);
			mcmf.addEdge(e[i].v,e[i].u,K,e[i].w);
		}
		int ans = mcmf.MincostMaxflow(0,n,K);
		if(ans == D) {
			printf("%lld\n",K);
		}else {
			printf("Impossible.\n");
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lengyue815

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值