参照:https://blog.csdn.net/qq_40674583/article/details/96632789
标准的贝尔曼福德
进行N-1次循环,松弛每一条边,如果还可以松弛,就说明有负
package com.company.POJ;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;
//SW练习_POJ3259_黑洞_贝尔曼福德
public class POJ32591116 {
static List<Edge32591116> edges;
static int N;
public static void main(String[] args) throws Exception{
BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st=new StringTokenizer(reader.readLine());
int T=Integer.parseInt(st.nextToken());//用例的个数
for (int i = 0; i <T ; i++) {
st=new StringTokenizer(reader.readLine());
N=Integer.parseInt(st.nextToken());//农场数
int M=Integer.parseInt(st.nextToken());//双向道路数
int W=Integer.parseInt(st.nextToken());//黑洞数
edges=new ArrayList<Edge32591116>();
for (int j = 0; j <M ; j++) {
st=new StringTokenizer(reader.readLine());
int s=Integer.parseInt(st.nextToken());//开始节点
int e=Integer.parseInt(st.nextToken());//结束节点
int t=Integer.parseInt(st.nextToken());//消耗时间
edges.add(new Edge32591116(s,e,t));
edges.add(new Edge32591116(e,s,t));
}
for (int j = 0; j <W ; j++) {
st=new StringTokenizer(reader.readLine());
int s=Integer.parseInt(st.nextToken());//开始节点
int e=Integer.parseInt(st.nextToken());//结束节点
int t=Integer.parseInt(st.nextToken());//缩短的时间
edges.add(new Edge32591116(s,e,-t));
}
System.out.printf("%s\n",process_bell_ford(edges,1));
}
reader.close();
}
public static String process_bell_ford(List<Edge32591116> edges,int start){
int[] len=new int[N+1];
Arrays.fill(len,1087654321);
len[start]=0;
for (int i = 1; i <N ; i++) {
for (Edge32591116 edge:edges) {
if(len[edge.end] >len[edge.from]+edge.time){
len[edge.end] =len[edge.from]+edge.time;
}
}
}
for (Edge32591116 edge:edges) {
if(len[edge.end] >len[edge.from]+edge.time){
//len[edge.end] =len[edge.from]+edge.time;
return "YES";
}
}
return "NO";
}
static class Edge32591116{
int from;
int end;
int time;
public Edge32591116(int from, int end, int time) {
this.from = from;
this.end = end;
this.time = time;
}
}
}
package info.frady.poj;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.*;
import java.util.Vector;
/**
* meng3.wei 2020.04.30
2
3 3 1
1 2 2
1 3 4
2 3 1
3 1 3
3 2 1
1 2 3
2 3 4
3 1 8
NO
YES
*/
public class POJ3259 {//Main
static String [] result;
static List<Egge3259>[] lists;
static int N,M,W;
public static int dis[];//存放起点到当前顶点的距离
public static int pid[];//存放当前节点的父亲节点,这个题目不需要求这个
public static int cnt[];//存放每个点被加入队列的次数,用于检查负环(如果一个点被放入了N次,肯定是有负环)
public static boolean inq[];//保存某点是否加入队列
public static LinkedList<Integer> li;//待访问的队列
public static void main(String[] args) throws Exception{
BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
int T=Integer.parseInt(reader.readLine());
result=new String[T];
for (int i = 0; i < T; i++) {
String str[]=reader.readLine().split(" ");
N=Integer.parseInt(str[0]);//农场的个数
M=Integer.parseInt(str[1]);//通道的个数
W=Integer.parseInt(str[2]);//黑洞的个数
lists=new ArrayList[N+1];
for (int j = 0; j <N+1 ; j++) {
lists[j]=new ArrayList<Egge3259>();
}
for (int j = 0; j < M; j++) {
str=reader.readLine().split(" ");
int start=Integer.parseInt(str[0]);
int end=Integer.parseInt(str[1]);
int len=Integer.parseInt(str[2]);
lists[start].add(new Egge3259(start,end,len));
lists[end].add(new Egge3259(end,start,len));
}
for (int j = 0; j < W; j++) {
str=reader.readLine().split(" ");
int start=Integer.parseInt(str[0]);
int end=Integer.parseInt(str[1]);
int len=Integer.parseInt(str[2]);
lists[start].add(new Egge3259(start,end,-len));
}
result[i]=bellean_ford(1);
}
for (int i = 0; i <T ; i++) {
System.out.println(result[i]);
}
reader.close();
}
private static String bellean_ford(int s) {
dis=new int[N+1];
pid=new int[N+1];
cnt=new int[N+1];
inq=new boolean[N+1];
Arrays.fill(dis,Integer.MAX_VALUE);
li=new LinkedList<Integer>();
li.add(s);
inq[s]=true;
dis[s]=0;
while(!li.isEmpty()){
int start=li.pop();
inq[start]=false;
//for (int i = 0; i <lists[start].size() ; i++) {
for(Egge3259 e : lists[start]){ //遍历每一个连接的边
if( dis[e.end] > dis[start]+e.distance){从start中转到end的距离
dis[e.end]=dis[start]+e.distance;
pid[e.end]=start;
if(!inq[e.end]){
li.add(e.end);
inq[e.end]=true;
cnt[e.end]=cnt[e.end]+1;
if(cnt[e.end]>N){
return "YES";
}
}
}
}
}
return "NO";//没有负环路
}
}
class Egge3259{
int start;
int end;
int distance;
public Egge3259(int start,int end,int distance){
this.start=start;
this.end=end;
this.distance=distance;
}
}