贝尔曼福特 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");
}
}
posted @ 2020-10-15 13:33  姓蜀名黍  阅读(121)  评论(0)    收藏  举报