UVA 1486 - Transportation(网络流+拆边)

UVA 1486 - Transportation

题目链接

题意:一个有向图上运输k货物,有一些边,每个边一个系数a,经过该边如果有x货物,就要缴纳a
x x的钱,问运输从1到n最小的代价

思路:费用流,这题边的容量c最大只有5,所以可以拆边,一条边拆成c条边,每条容量1,对应相应的代价为a * (i^2 - (i - 1)^2),然后跑一下费用流即可

代码:

#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

const int MAXNODE = 105;
const int MAXEDGE = 200005;
typedef int Type;
const Type INF = 0x3f3f3f3f;

struct Edge {
	int u, v;
	Type cap, flow, cost;
	Edge() {}
	Edge(int u, int v, Type cap, Type flow, Type cost) {
		this->u = u;
		this->v = v;
		this->cap = cap;
		this->flow = flow;
		this->cost = cost;
	}
};

struct MCFC {
	int n, m, s, t;
	Edge edges[MAXEDGE];
	int first[MAXNODE];
	int next[MAXEDGE];
	int inq[MAXNODE];
	Type d[MAXNODE];
	int p[MAXNODE];
	Type a[MAXNODE];

	void init(int n) {
		this->n = n;
		memset(first, -1, sizeof(first));
		m = 0;
	}

	void add_Edge(int u, int v, Type cap, Type cost) {
		edges[m] = Edge(u, v, cap, 0, cost);
		next[m] = first[u];
		first[u] = m++;
		edges[m] = Edge(v, u, 0, 0, -cost);
		next[m] = first[v];
		first[v] = m++;
	}

	bool bellmanford(int s, int t, Type &flow, Type &cost) {

		for (int i = 0; i < n; i++) d[i] = INF;
		memset(inq, false, sizeof(inq));
		d[s] = 0; inq[s] = true; p[s] = s; a[s] = INF;
		queue<int> Q;
		Q.push(s);
		while (!Q.empty()) {
			int u = Q.front(); Q.pop();
			inq[u] = false;
			for (int i = first[u]; i != -1; i = next[i]) {
				Edge& e = edges[i];
				if (e.cap > e.flow && d[e.v] > d[u] + e.cost) {
					d[e.v] = d[u] + e.cost;
					p[e.v] = i;
					a[e.v] = min(a[u], e.cap - e.flow);
					if (!inq[e.v]) {Q.push(e.v); inq[e.v] = true;}
				}
			}
		}
		if (d[t] == INF) return false;
		flow += a[t];
		cost += d[t] * a[t];
		int u = t;
		while (u != s) {
			edges[p[u]].flow += a[t];
			edges[p[u]^1].flow -= a[t];
			u = edges[p[u]].u;
		}
		return true;
	}

	Type Mincost(int s, int t, Type D) {
		Type flow = 0, cost = 0;
		while (bellmanford(s, t, flow, cost));
		if (D != flow) return -1;
		return cost;
	}
} gao;

int n, m, k;

int main() {
	while (~scanf("%d%d%d", &n, &m, &k)) {
		gao.init(n + 1);
		gao.add_Edge(0, 1, k, 0);
		int u, v, a, c;
		while (m--) {
			scanf("%d%d%d%d", &u, &v, &a, &c);
			for (int i = 1; i <= c; i++) {
				gao.add_Edge(u, v, 1, a * (i * i - (i - 1) * (i - 1)));
			}
		}
		printf("%d\n", gao.Mincost(0, n, k));
	}
	return 0;
}
时间: 2024-08-01 13:57:56

UVA 1486 - Transportation(网络流+拆边)的相关文章

uva 1486 Transportation (最大流+拆边)

uva 1486 Transportation Description There are N cities, and M directed roads connecting them. Now you want to transport K units of goods from city 1 to city N. There are many robbers on the road, so you must be very careful. The more goods you carry,

HDU 3667 Transportation(网络流之费用流)

题目地址:HDU 3667 这题的建图真是巧妙...为了保证流量正好达到k,需要让每一次增广到的流量都是1,这就需要把每一条边的流量都是1才行.但是每条边的流量并不是1,该怎么办呢.这个时候可以拆边,反正c最多只有5,拆成5条流量为1的边.但是这时候费用怎么办呢,毕竟平方的关系不能简单把每一条边加起来.这时候可以把拆的边的流量设为1,3,5,7,9.如果经过了3个流量,那就肯定会流1,3,5,费用为9,是3的平方,同理,其他的也是如此.然后按照给出的边建图跑一次费用流就可以了. 代码如下: #i

uva 301 Transportation(回溯)

uva 301 Transportation Ruratania is just entering capitalism and is establishing new enterprising activities in many fields including transport. The transportation company TransRuratania is starting a new express train from city A to city B with seve

POJ 3228-Gold Transportation(网络流_最大流+二分查找)

Gold Transportation Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 2995   Accepted: 1065 Description Recently, a number of gold mines have been discovered in Zorroming State. To protect this treasure, we must transport this gold to the

uva 563 - Crimewave 网络流

题目链接 有一个n*m的图, 里面有q个人, 每个点只能走一次, 问这q个人是否都能够走出这个图. 对于每个人, 建边(s, u, 1), 对于每个边界的格子, 建边(u', t, 1), 对于其他格子, 建边(u, u', 1), 以及(u', v, 1), v是它四周的格子. 对于求出的最大流, 如果等于人数, 则可以走出. 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define pb(x) push_back(x) 4 #de

A Plug for UNIX UVA - 753(网络流)

题意:n个插座,m个设备及其插头类型,k种转换器,没有转换器的情况下插头只能插到类型名称相同的插座中,问最少剩几个不匹配的设备 lrj紫书里面讲得挺好的. 先跑一遍floyd,看看插头类型a能否转换为b 然后构造网络 源点为0, 汇点为n + m + 1,源点连插头 容量为1,插座连汇点,容量为1 插头和插座能互相转换的容量为INF,跑一遍最大流 m - 最大流就是答案 顺便粘一下dinic的板子 #include <bits/stdc++.h> using namespace std; in

图论常用算法之一 POJ图论题集【转载】

POJ图论分类[转] 一个很不错的图论分类,非常感谢原版的作者!!!在这里分享给大家,爱好图论的ACMer不寂寞了... (很抱歉没有找到此题集整理的原创作者,感谢知情的朋友给个原创链接) POJ:http://poj.org/ 1062* 昂贵的聘礼 枚举等级限制+dijkstra 1087* A Plug for UNIX 2分匹配 1094 Sorting It All Out floyd 或 拓扑 1112* Team Them Up! 2分图染色+DP 1125 Stockbroker

UVA 1306 - The K-League(网络流)

UVA 1306 - The K-League 题目链接 题意:n个球队,已经有一些胜负场,现在还有一些场次,你去分配胜负,问每支球队有没有可能获胜 思路:网络流公平分配模型,把场次当作任务,分配给人,然后先贪心,枚举每个人,让这些人能赢的都赢,剩下的去建图,每个源点连向比赛容量为场次,每个比赛连向2个球队,容量无限大,每个球队连向汇点,容量为每个的人的总和减去当前已经赢的,建完图跑一下最大流,然后判断源点流出的是否都满流即可 代码: #include <cstdio> #include &l

UVA 10249 - The Grand Dinner(网络流 or 贪心)

UVA 10249 - The Grand Dinner 题目链接 题意:给定几队队员,几张桌子,每队有一个人数,每个桌子也有一个容量上限,要求一种安排方案,使得没有同队人坐在一个桌子上,求方案 思路:明显贪心可以搞- -, 每次往容量最多的桌子塞就可以了..不过这题既然出在网络流这章,还是用网络流也搞了下 源点连到每队,桌子连到汇点,容量就是容量,然后每队和每个桌子相连,容量为1,表示一个桌子只能做一个队员,然后跑一下最大流即可 代码: 网络流: #include <cstdio> #inc