UVA 11478 Halum(差分约束系统+Bellman-Ford)



题意:给定一个有向图,每条边都有一个权值。每次你可以选择一个结点v和一个整数d,把所有以v为终点的边的权值减小d,把所有以v为起点的边的权值增加d,最后让所有边的权值的最小值大于零且尽量大。

ps:lrj的书上有个坑,说上说非负,其实原题说要大于0.....wa了好几发

分析:因为不同的操作互不影响,因此可以按任意顺序实施这些操作。另外,对于同一个点的多次操作可以合并,因此可以令sum(u)为作用于结点u之上的所有d之和。这样,本题的目标就是确定所有的sum(u),使得操作之后所有边权的最小值尽量大。

“最小值最大”使用二分答案的方法。二分答案x之后,问题转化为是否可以让操作完毕后每条边的权值均不小于x。对于边a->b,不难发现操作完毕后它的权值为w(a,b)+sum(a)-sum(b),因此每条边a->b都可以列出一个不等式w(a,b)+sum(a)-sum(b)>=x,移项得sum(b)-sum(a)<=w(a,b)-x。这样,我们实际得到一个差分约束系统。

查分约束系统是指一个不等式组,每个不等式形如xj-xi<=bk,这里的bk是一些事先已知的常数。这个不等式类似于最短路中的不等式d[v]<=d[u]+w(u,v),我们可以用最短路算法求解:对于约束条件xj-xi《=bk,新建一条边i-->j,权值为bk。如果图中有负权环,则差分约束系统无解。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#define eps 1e-4
#define LL long long
using namespace std;  

const int maxn = 500 + 10;
const int INF = 0x3f3f3f3f;

//Bellman-Ford算法
struct Edge {
	int from, to;
	int dist;
	Edge(int u = 0, int v = 0, double d = 0) : from(u), to(v), dist(d) {
	}
};
struct BellmanFord{
	int n, m;
	vector<Edge> edges;
	vector<int> G[maxn];
	bool inq[maxn];
	int d[maxn];
	int p[maxn];
	int cnt[maxn];

	void init(int n) {
		this->n = n;
		for(int i = 0; i < n; i++) G[i].clear();
		edges.clear();
	}

	void AddEdges(int from, int to, int dist) {
		edges.push_back(Edge(from, to, dist));
		m = edges.size();
		G[from].push_back(m-1);
	}

	bool bellman_ford(int S) {
		queue<int> Q;
		memset(inq, 0, sizeof(inq));
		memset(cnt, 0, sizeof(cnt));
		for(int i = 0; i < n; i++) d[i] = INF;
		d[S] = 0;
		inq[S] = true;
		Q.push(S);
		while(!Q.empty()) {
			int u = Q.front(); Q.pop();
			inq[u] = false;
			for(int i = 0; i < G[u].size(); i++) {
				Edge& e = edges[G[u][i]];
				if(d[u]<INF && d[e.to]>d[u]+e.dist) {
					d[e.to] = d[u] + e.dist;
					p[e.to] = G[u][i];
					if(!inq[e.to]) {
						Q.push(e.to);
						inq[e.to] = true;
						if(++cnt[e.to] > n) return false;
					}
				}
			}
		}
		return true;
	}
	bool negetiveCycle() {
		queue<int> Q;
		memset(inq, 0, sizeof(inq));
		memset(cnt, 0, sizeof(cnt));
		for(int i = 0; i < n; i++) {
			d[i] = 0; inq[0] = true; Q.push(i);
		}
		while(!Q.empty()) {
			int u = Q.front(); Q.pop();
			inq[u] = false;
			for(int i = 0; i < G[u].size(); i++) {
				Edge& e = edges[G[u][i]];
				if(d[e.to]>d[u]+e.dist) {
					d[e.to] = d[u] + e.dist;
					p[e.to] = G[u][i];
					if(!inq[e.to]) {
						Q.push(e.to);
						inq[e.to] = true;
						if(++cnt[e.to] > n) return true;
					}
				}
			}
		}
		return false;
	}

} solver; 

int n, m;
bool test(int w) {
	for(int i = 0; i < m; i++) solver.edges[i].dist -= w;
	int t = solver.negetiveCycle();
	for(int i = 0; i < m; i++) solver.edges[i].dist += w;
	return t;
}

int kase;
int main() {
	freopen("input.txt", "r", stdin);
	while(scanf("%d%d", &n, &m) == 2) {
		solver.init(n);
		for(int i = 0; i < m; i++) {
			int u, v, d;
			cin >> u >> v >> d;
			u--; v--;
			solver.AddEdges(u, v, d);
		}
		int L = 0, R = 10000;
		if(test(1)) puts("No Solution");
		else if(!test(R+5)) puts("Infinite");
		else {
			while(L <= R) {
				int M = (R+L)/2;
				if(test(M)) R = M - 1;
				else L = M + 1;
			}
			printf("%d\n", R);
		}
	}
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-09 21:23:37

UVA 11478 Halum(差分约束系统+Bellman-Ford)的相关文章

UVA - 11478 Halum(差分约束系统)

题目大意:有一种操作(u,c),表示所有以u为终点的边的权值减去c,所有以u为起点的边权值加上c 最后要求所有的边的权值非负且尽量大 解题思路:最小且最大,二分,枚举边的最小权值,然后看是否符合 对于给出的所有有向线段(u,v,val) 所有对u和v的操作才会影响到这条边,对其他点的操作并不会影响到,所以可以将边分开出来讨论 假设对u的操作为d[u],对v的操作为d[v],那么这条边的权值就变成了 d[u] - d[v] + val 假设枚举的边权值为w,那么这条边就要满足 d[u] - d[v

UVA 11478 Bellman-Ford+差分约束系统

[题意]: 给出一张有向图(信息为点数,边数,每条边的起点终点和权值),然后可以让你做任意次如下操作: 选择任意节点v和一个数值d,使以v为终点的边的权值减d,以v为起点的边的权值加d, 最后要满足两个条件:这些边的权值为非负,这些边中权值最小的边的权值尽量大.[知识点]: Bellman-Ford+差分约束系统[题解]: 差分约束系统:是判断不等式组有解的一种方法(具体原理还不甚理解,以后还会具体补充该文章) 例如有若干不等式形如xj-xi<=ak 那么以i为起点j为终点ak为权值建图,然后用

UVA 11478 bf+差分约束系统+二分逼近

Halum You are given a directed graph G(V, E) with a set of vertices and edges. Each edge (i, j) that connects some vertex i to vertex j has an integer cost associated with that edge. Define the operation Halum(v, d) to operate on a vertex v using an

UVA 11478 Halum (差分约束)

题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2473 题解: 首先我们可以得到的约束条件形如 xi - xj <= b[k] ,即可以转换为 j - > i连边,且权值为b[k],这样建图后我们判断是否有解,只需要用spfa跑负圈就可以了. 如果存在负圈,原差分系统定然无解. 简单证明: 我们不妨设这个环为 x1,

PKU 3169 Layout(差分约束系统+Bellman Ford)

题目大意:原题链接 当排队等候喂食时,奶牛喜欢和它们的朋友站得靠近些.FJ有N(2<=N<=1000)头奶牛,编号从1到N,沿一条直线站着等候喂食.奶牛排在队伍中的顺序和它们的编号是相同的.因为奶牛相当苗条,所以可能有两头或者更多奶牛站在同一位置上(即间距可能为0).即是说,如果我们想象奶牛是站在一条数轴上的话,允许有两头或更多奶牛拥有相同的横坐标. 一些奶牛相互间存有好感,它们希望两者之间的距离不超过一个给定的数L.另一方面,一些奶牛相互间非常反感,它们希望两者间的距离不小于一个给定的数D.

uva 11478 Halum(图论-差分约束)

  Problem H Halum Time Limit : 3 seconds   You are given a directed graph G(V,E) with a set of vertices and edges. Each edge (i,j) that connects some vertex i to vertex j has an integer cost associated with that edge. Define the operation Halum(v, d)

UVA 11478 - Halum(差分约束+最短路)

UVA 11478 - Halum 题目链接 题意:给定一个有向图,每次操作可以选择一个结点,把以这个点为起点的边权值+d,以这个边为终点的-d,问经过操作后,能得到的边权最小的最大值是多少,并且要判但是否无穷大或无解 思路:转化为差分约束,设一条边,他增加的权值为sum(u)减少了sum(v),那么二分答案x,得到一个不等式sum(u) - sum(v) + w(u, v) >= x,变形后得到sum(v) - sum(u) <= w(u, v) - x,这样就转化为了差分约束,直接bell

UVA - 11478 Halum (最短路应用+二分)

Description   Problem H Halum Time Limit : 3 seconds     You are given a directed graph G(V,E) with a set of vertices and edges. Each edge (i,j) that connects some vertex i to vertex j has an integer cost associated with that edge. Define the operati

UVA 11478 Halum(差分约束)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34651 [思路] 差分约束系统. 设结点u上的操作和为sum[u],则边(u,v)权值为d-sum[v]+sum[u].对于最小值最大问题我们想到二分答案,设二分值为x,则问题变为判断最小值为x时题目是否存在解.对于权值我们有不等式d-sum[v]+sum[u]>=x  =>  sum[v]<=sum[u]+(d-x),由此可以建立差分约束系统. 无解:如