음수간선이 존재하는 문제였다.
bfs로 고민하니 뭔가 cycle이 생기고 왔던 노드를 다시 지나고 하는것이 어떻게 해야할지 모르겠었다.
심지어 최단거리 문제를 푼지 오래되어 디익스트라도 생각나지 않았었지만, 디익스트라도 아니었다.
처음으로 벨만포드문제를 접하게 되었다.
사실 아직 벨만포드알고리즘이 다 이해가 되지는 않는다.
하지만 동작 방식 자체는 이해가 잘 되지 않아 일단은 보편적으로 벨만포드 알고리즘 문제를 푸는 방식만을 생각했다.
현재는 이해가 다 되진 않지만 개인적으로 설명이 좋다고 생각되는 글
일단, 가장 중요한것은, 벨만포드던, 디익스타라던, 특정한 노드로부터, 각 노드까지의 최단경로를 구하는 방식이라는 것이다.
벨만포드는, 후에, node의 개수를 v라고 한다면, v-1 번만큼 다음을 반복한다.
벨만포드는, "음수간선"으로 인한 사이클의 존재를 확인할 수 있다. 위의 반복하는 과정을 한 번 더 수행한다.
하지만 벨만포드도 다 이해가 되지 않았기에 이 분의 글에서 내가 이해할 수 있는 부분만을 뽑아서, 다시 풀었다.
맞았습니다가 떴지만 완전히 이해하지 못했다.
public class Main {
public static final int TIME_INIT = 10001;
public static int n,m,w; // the number of nodes, edges, holes
public static int[][] matrix = new int[500][500];
//public static List<int[]>[] graph = new ArrayList[500];
public static List<int[]> edges = new ArrayList<>();
public static int[] dist = new int[500];
public static void Setting() throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
int test =0,v1=0,v2=0,c=0;
test = Integer.parseInt(br.readLine());
for(int t=0;t<test;t++){
st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
w = Integer.parseInt(st.nextToken());
// init dist table as the start node is 0
Arrays.fill(dist, 0);
// init matrix
for(int i=0;i<n;i++)
Arrays.fill(matrix[i],TIME_INIT);
// get the edge info
for(int e=0;e<m;e++){
st = new StringTokenizer(br.readLine());
v1 = Integer.parseInt(st.nextToken())-1;
v2 = Integer.parseInt(st.nextToken())-1;
c = Integer.parseInt(st.nextToken());
if(matrix[v1][v2]>c) matrix[v1][v2]=c;
if(matrix[v2][v1]>c) matrix[v2][v1]=c;
}
// get the hole info
for(int h=0;h<w;h++){
st = new StringTokenizer(br.readLine());
v1 = Integer.parseInt(st.nextToken())-1;
v2 = Integer.parseInt(st.nextToken())-1;
c = Integer.parseInt(st.nextToken())*(-1);
if(matrix[v1][v2]>c) matrix[v1][v2]=c;
}
boolean res =solve();
if(res) System.out.println("YES");
else System.out.println("NO");
}
}
public static void print(){
System.out.println();
for(int i=0;i<n;i++){
System.out.print(dist[i]+",");
}
}
// if return true --> it has cycle of negative edge
public static boolean solve() {
// n 번 수행하는 것은, 음의간선 순회를 확인하기 위함.
int cur=0,next=0,c=0;
for(int i=0;i<n;i++){
// 모든 간선에 대하여 수행 한다. 간선을
for(int start=0;start<n;start++){
for(int end=0;end<n;end++){
// 이거는 간선이 아님
if(matrix[start][end]==TIME_INIT)continue;
// 갱신이 일어나는 경우
if(dist[end]>(dist[start]+matrix[start][end])){
dist[end]=dist[start]+matrix[start][end];
//print();
if(i == n-1) return true;
}
}
}
}
return false;
}
public static void main(String[] args) throws IOException {
Setting();
}
}