贝尔曼福特 POJ3259 和POJ1860
原理
松弛
每次松弛操作实际上是对相邻节点的访问,第
次松弛操作保证了所有深度为n的路径最短。由于图的最短路径最长不会经过超过
条边,所以可知贝尔曼-福特算法所得为最短路径。
负边权操作
与迪科斯彻算法不同的是,迪科斯彻算法的基本操作“拓展”是在深度上寻路,而“松弛”操作则是在广度上寻路,这就确定了贝尔曼-福特算法可以对负边进行操作而不会影响结果。
负权环判定
因为负权环可以无限制的降低总花费,所以如果发现第
次操作仍可降低花销,就一定存在负权环。
虫洞
package pro.proclass.chaopengfan; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.Arrays; import java.util.StringTokenizer; public class VjudgeN { static class Edge { int s; int e; int v; public Edge(int s, int e, int v) { this.s = s; this.e = e; this.v = v; } } public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); int f = Integer.parseInt(st.nextToken()); for (int i = 0; i < f; i++) { st = new StringTokenizer(br.readLine()); int N = Integer.parseInt(st.nextToken()); int M = Integer.parseInt(st.nextToken());// 路径 int W = Integer.parseInt(st.nextToken());// 虫洞 Edge[] edges = new Edge[W+2*M]; int idx = 0; for (int j = 0; j < M; j++) { st = new StringTokenizer(br.readLine()); int s = Integer.parseInt(st.nextToken()); int e = Integer.parseInt(st.nextToken());// 路径 int t = Integer.parseInt(st.nextToken());// 虫洞 edges[idx++] = new Edge(s, e, t); edges[idx++] = new Edge(e, s, t); } for (int j = 0; j < W; j++) { st = new StringTokenizer(br.readLine()); int s = Integer.parseInt(st.nextToken()); int e = Integer.parseInt(st.nextToken());// 路径 int t = Integer.parseInt(st.nextToken());// 虫洞 edges[idx++] = new Edge(s, e, -t); } int[] dp = new int[N+1]; Arrays.fill(dp, 5000000); for (int j = 0; j < N; j++) { for (int k = 0; k < idx; k++) { int s = edges[k].s; int e = edges[k].e; int t = edges[k].v; if(dp[e] > dp[s] + t) { dp[e] = dp[s] + t; } } } boolean res = false; for (int k = 0; k < idx; k++) { int s = edges[k].s; int e = edges[k].e; int t = edges[k].v; if(dp[e] > dp[s] + t) { dp[e] = dp[s] + t; res = true; break; } } System.out.println(res ? "YES" : "NO"); } } }
货币交换
package pro.proclass.chaopengfan;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class VjudgeO {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken()); // 货币数量
int m = Integer.parseInt(st.nextToken()); // 兑换点数量
int s = Integer.parseInt(st.nextToken()); // 拥有的货币编号
double v = Double.parseDouble(st.nextToken());
double[][] edge = new double[2*m][4];
double[] d = new double[n+1];
d[s] = v;
int idx = 0;
for (int i = 0; i < m; i++) {
st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
double Rab = Double.parseDouble(st.nextToken());
double Cab = Double.parseDouble(st.nextToken());
double Rba = Double.parseDouble(st.nextToken());
double Cba = Double.parseDouble(st.nextToken());
edge[idx][0] = a;
edge[idx][1] = b;
edge[idx][2] = Rab;
edge[idx++][3] = Cab;
edge[idx][0] = b;
edge[idx][1] = a;
edge[idx][2] = Rba;
edge[idx++][3] = Cba;
}
for (int i = 1; i < n; i++) {
for (int j = 0; j < idx; j++) {
int ss = (int)edge[j][0];
int ee = (int)edge[j][1];
if(d[ee] < (d[ss] - edge[j][3]) * edge[j][2]) {
d[ee] = (d[ss] - edge[j][3]) * edge[j][2];
}
}
}
boolean res = false;
for (int j = 0; j < idx; j++) {
int ss = (int)edge[j][0];
int ee = (int)edge[j][1];
if(d[ee] < (d[ss] - edge[j][3]) * edge[j][2]) {
res = true;
}
}
System.out.println(res ? "YES" :"NO");
}
}

浙公网安备 33010602011771号