首页 > 代码库 > UVA - 11478 Halum (最短路应用+二分)
UVA - 11478 Halum (最短路应用+二分)
Description
Problem H | Halum | Time Limit : 3 seconds | ||
As an example of that operation, consider graph G that has three vertices named (1, 2, 3) and two edges. Edge (1, 2) has cost -1, and edge (2,3) has cost 1. The operation Halum(2,-3) operates on edges entering and leaving vertex 2. Thus, edge (1, 2) gets cost -1-(-3)=2 and the edge (2, 3) gets cost 1 + (-3) = -2. Your goal is to apply the Halum function to a graph, potentially repeatedly, until every edge in the graph 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) andE(E≤2700). E lines follow. Each line represents a directed edge using three space-separated integers (u, v, d). Absolute value of cost can be at 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 | Sample Output | |||
2 1 | Infinite |
题意:给定一个有向图,每条边都有一个权值,每次你可选择一个结点v和一个整数d,把所有以v为终点的边的权值减少d,把所有以v为终点的边的权值增加d,最后要让所有边的最小值非负且尽量大。
思路:最小值最大,很显然想到二分答案,可以令sum(u)表示为作用在节点u之上的所有d之和,这样题目的目标就是确定所有的sum(u)了; 对于边a->b,不难发现操作后的权值是:w(a, b)+sum(a)-sum(b)>=x
那么就可以得到个不等式:sum(b)-sum(a) <= w(a, b)-x,而w(a, b)-x我们是已知的,那么就能得到相当于最短路的
不等式 d[v]<=d[u]+w(u, v),那么我们就可以构建一个新图,那么我们在做Bellman-Ford的时候,如果发现负权环的话,那么就相当于我们无法得到一个类似最短路的不等式,所有无解
#include <iostream> #include <cstring> #include <algorithm> #include <cstdio> #include <queue> #include <vector> using namespace std; const int maxn = 505; const int inf = 0x3f3f3f3f; struct Edge { int from, to, dist; }; struct BellmanFord { int n, m; vector<Edge> edges; vector<int> G[maxn]; int 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 AddEdge(int from, int to, int dist) { edges.push_back((Edge){from, to, dist}); m = edges.size(); G[from].push_back(m-1); } bool negativeCycle(int tmp) { 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] = 1; Q.push(i); } while (!Q.empty()) { int u = Q.front(); Q.pop(); inq[u] = 0; for (int i = 0; i < G[u].size(); i++) { Edge &e = edges[G[u][i]]; if (d[e.to] > d[u] + e.dist - tmp) { d[e.to] = d[u] + e.dist - tmp; p[e.to] = G[u][i]; if (!inq[e.to]) { Q.push(e.to); inq[e.to] = 1; if (++cnt[e.to] > n) return 1; } } } } return 0; } }; BellmanFord solve; int n, m; int main() { int u, v, w; while (scanf("%d%d", &n, &m) != EOF) { solve.init(n); int l = 1, r = 0, mid; for (int i = 0; i < m; i++) { scanf("%d%d%d", &u, &v, &w); u--, v--; solve.AddEdge(u, v, w); r = max(r, w); } if (solve.negativeCycle(1)) printf("No Solution\n"); else if (!solve.negativeCycle(r+1)) printf("Infinite\n"); else { while (l < r) { mid = l + (r-l+1)/2; if (solve.negativeCycle(mid)) r = mid-1; else l = mid; } printf("%d\n", l); } } return 0; }