Description
![Download as PDF Download as PDF](http://uva.onlinejudge.org/components/com_onlinejudge/images/button_pdf.png)
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) and E(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;
}