Reputation:
Solving this Arbitage problem of UVA http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=40 but I am stuck with finding the negative cycle of shortest length(length here is number of vertices).Here is my code that successfully detects the negative cycle
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
public class _104 {
public static void main(String[] args) throws NumberFormatException,
IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(
System.in));
String input;
while ((input = reader.readLine()) != null) {
int n = Integer.parseInt(input);
double[][] cost = new double[n + 1][n + 1];
double[] spEstimate = new double[n + 1];
int parent[] = new int[n + 1];
for (int i = 0; i < n + 1; i++) {
spEstimate[i] = Double.MAX_VALUE;
cost[0][i] = 0;
cost[i][0] = Double.MAX_VALUE;
parent[i] = Integer.MAX_VALUE;
}
spEstimate[0] = 0.0;
parent[0] = 0;
for (int i = 1; i < n + 1; i++) {
String[] line = reader.readLine().split("\\s+");
for (int j = 1; j < n + 1; j++) {
if (i == j) {
cost[i][j] = 0;
} else if (i < j) {
cost[i][j] = -(Math
.log(Double.parseDouble(line[j - 2])) / Math
.log(2));
} else {
cost[i][j] = -(Math
.log(Double.parseDouble(line[j - 1])) / Math
.log(2));
}
}
}
int save = 1, s = 1;
boolean flag = BellmanFord(n, cost, spEstimate, parent);
display(cost);
// Relax all edges once more
boolean brk = true;
for (int i = 0; i < cost.length && brk; i++) {
for (int j = 0; j < cost.length && brk; j++) {
//relax(i, j, spEstimate, cost[i][j], parent);
}
}
ArrayList<Integer> path = new ArrayList<Integer>();
while (parent[save] != s) {
path.add(save);
save = parent[save];
}
if (flag) {
System.out.println("no arbitrage sequence exists");
} else {
path.add(0, path.get(path.size() - 1));
for (int i = path.size() - 1; i >= 0; --i) {
System.out.println(path.get(i));
}
}
}
reader.close();
}
public static boolean BellmanFord(int n, double[][] cost, double[] sp,
int[] parent) {
for (int k = 0; k < n - 1; k++) {
for (int i = 0; i < cost.length; i++) {
for (int j = 0; j < cost.length; j++) {
relax(i, j, sp, cost[i][j], parent);
}
}
}
// Relax all edges once more to detect cycle
for (int i = 0; i < cost.length; i++) {
for (int j = 0; j < cost.length; j++) {
if (sp[j] > (sp[i] + cost[i][j])) {
return false;
}
}
}
return true;
}
static void relax(int i, int j, double[] sp, double cij, int[] parent) {
if (sp[j] > (sp[i] + cij)) {
sp[j] = sp[i] + cij;
System.out.println("relaxed " + i + " " + j + " " + cij + " "
+ sp[i] + " " + sp[j]);
parent[j] = i;
}
}
static void display(double[][] cost) {
System.out.println("Display Cost");
for (int i = 0; i < cost.length; i++) {
for (int j = 0; j < cost.length; j++) {
System.out.print(cost[i][j] + "\t");
}
System.out.println();
}
}
static void display(double[] sp) {
for (int i = 0; i < sp.length; i++) {
System.out.println(sp[i]);
}
}
}
Upvotes: 3
Views: 1208
Reputation: 362
It is possible to solve this problem by considering cycles of increasing length as opposed to finding negative cycles as described by kraskevich. The worst case complexity for both approaches is O(n^4). This approach resembles Floyd-Warshall where you consider increasing lengths instead of intermediate vertices.
You can find a detailed explanation that includes diagrams and code here.
Upvotes: 0
Reputation: 18556
You can do it like that:
Fix the start vertex of the cycle(let's call it v
).
Run Ford-Bellman algorithm assuming that dist[i] = 0 if i = v and INF otherwise
.
If there is a negative cycle that contains v
, after k
iterations of the outer loop in Ford-Bellman algorithm dist[v]
will become negative. So you can easily find such smallest k
by simply checking if dist[v]
is still non-negative or not after each iteration.
The smallest k
among all v
is the answer.
Upvotes: 1