UVA 11478 Halum(二分+SPFA算法)

You are given a directed graph G(V, E) with a set of vertices and edges. Each edge (i, j) that connectssome 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 integer d as follows: subtractd from the cost of all edges that enter v and add d to the cost of every edge that leaves v.As an example of that operation, consider graph G that has three vertices named (1, 2, 3) and twoedges. Edge (1, 2) has cost -1, and edge (2,3) has cost 1. The operation Halum(2, −3) operates onedges entering and leaving vertex 2. Thus, edge (1, 2) gets cost -1-(-3)=2 and the edge (2, 3) gets cost1 + (-3) = -2.Your goal is to apply the Halum function to a graph, potentially repeatedly, until every edge in thegraph has at least a certain cost that is greater than zero. You have to maximize this cost.

Input

Two space-separated integers per case: V (V ≤ 500) and E (E ≤ 2700). E lines follow. Each linerepresents a directed edge using three space-separated integers (u, v, d). Absolute value of cost can beat most 10000.

Output

If the problem is solvable, then print the maximum possible value. If there is no such solution print‘No Solution’. If the value can be arbitrary large print ‘Infinite’

Sample Input

2 1

1 2 10

2 1

1 2 -10

3 3

1 2 4

2 3 2

3 1 5

4 5

2 3 4

4 2 5

3 4 2

3 1 0

1 2 -1

Sample Output

Infinite

Infinite

3

1


【思路】

我们考察某一条边,起点记为a,终点为b,对a、b进行一次题述操作,那么原来边的权值就会变为weight + sum(a) - sum(b)。要求进行适当操作后,所有边为正,且最短边尽可能长。我们假想最短边长度为x,即意味着对任意边,weight + sum(a) - sum(b) >= x,经过变换,可得sum(b) <= sum(a) + weight - x,也就是说整个图需满足此差分约束,这就让我们联想到最短路的松弛公式,在此sum即最短路的d。而最短路存在的条件是不存在负环,所以可以二分最短边,用SPFA算法判负环,得到的最大的不存在负环的最短边即答案。


【代码】

//************************************************************************
// File Name: main.cpp
// Author: Shili_Xu
// E-Mail: [email protected] 
// Created Time: 2018年03月29日 星期四 18时03分19秒
//************************************************************************

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

const int MAXN = 505, INF = 0x3f3f3f3f;

struct edge {
	int from, to, dist;

	edge() {} 
	edge(int _from, int _to, int _dist) : from(_from), to(_to), dist(_dist) {}
};

int n, m;
vector<edge> e;
vector<int> g[MAXN];
long long d[MAXN];
int cnt[MAXN];
bool inq[MAXN];
queue<int> q;

void add_edge(int from, int to, int dist)
{
	e.push_back(edge(from, to, dist));
	g[from].push_back(e.size() - 1);
}

bool spfa(int x)
{
	memset(cnt, 0, sizeof(cnt));
	memset(d, 0x3f, sizeof(d));
	memset(inq, false, sizeof(inq));
	d[x] = 0; q.push(x); inq[x] = true;
	while (!q.empty()) {
		int u = q.front(); q.pop(); inq[u] = false;
		for (int i = 0; i < g[u].size(); i++) {
			edge &now = e[g[u][i]];
			if (d[now.to] > d[u] + now.dist) {
				d[now.to] = d[u] + now.dist;
				if (!inq[now.to]) {
					q.push(now.to);
					inq[now.to] = true;
					if (++cnt[now.to] == n) return true;
				}
			}
		}
	}
	return false;
}

bool check(int x)
{
	for (int i = 0; i < e.size(); i++) e[i].dist -= x;
	bool ans = spfa(0);
	for (int i = 0; i < e.size(); i++) e[i].dist += x;
	return ans;
}

void init()
{
	e.clear();
	for (int i = 0; i <= n; i++) g[i].clear();
}

int main()
{
	while (scanf("%d %d", &n, &m) == 2) {
		init();
		int a, b, c, mx = -INF;
		for (int i = 1; i <= m; i++) {
			scanf("%d %d %d", &a, &b, &c);
			add_edge(a, b, c);
			mx = max(mx, c);
		}
		for (int i = 1; i <= n; i++) add_edge(0, i, 0);
		if (check(1)) {
			printf("No Solution\n");
			continue;
		}
		if (!check(mx)) {
			printf("Infinite\n");
			continue;
		}
		int l = 1, r = mx, ans = 0;
		while (l <= r) {
			int mid = (l + r) >> 1;
			if (check(mid))
				r = mid - 1;
			else {
				ans = mid;
				l = mid + 1;
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/shili_xu/article/details/79791203
今日推荐