[문제][Algospot] PROMISES(선거공약)
2018. 4. 22. 12:33ㆍ[개발] 지식/알고리즘 문제풀이
비슷한 문제를 시험장에서도 본 것 같다.
가장 직관적인 생각은 노드나 간선이 추가될때마다 Floyd 알고리즘을 반복실행하는 것이다.
하지만 V^3의 시간복잡도인 Floyd 알고리즘을 매번 실행하면 당연히 시간초과가 날 수밖에 없다.
핵심은 Floyd Warshall 을 활용하면서 간선이 추가될때마다 update를 해주는것이다.
하지만 항상 update가 시간이 많이 걸려서 실패했던 기억이..
따라서 노드가 아닌 간선이 추가되는 관점에서 개량된 Floyd를 사용하면 V^2 시간복잡도로 매번 갱신할 수 있다.
아래 소스는 '알고리즘 문제 해결 전략 2'의 풀이에 나온것을 JAVA로 변환한 것이다.
package apss;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;
public class Promises {
public static int V,M,N;
public static long adj[][],dist[][];
public static int result;
public static void main(String[] args) throws NumberFormatException, IOException {
// TODO Auto-generated method stub
// 테스트 커밋2
System.setIn(new FileInputStream("D:\\sample_input.txt"));
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int T = Integer.parseInt(br.readLine());
for(int tc=1; tc<=T; tc++) {
StringTokenizer st = new StringTokenizer(br.readLine());
V = Integer.parseInt(st.nextToken()); // V (2 <= V <= 200)
M = Integer.parseInt(st.nextToken()); // 0 <= M+N <= 1000
N = Integer.parseInt(st.nextToken());
adj = new long[V][V];
dist = new long[V][V];
// 0 <= a,b <= V-1, 1 <= c <= 100000
for(int i=0; i<M; i++) {
st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
int c = Integer.parseInt(st.nextToken());
if(adj[a][b] > 0) {
if(c < adj[a][b]) {
adj[a][b] = c;
adj[b][a] = c;
}
}else {
adj[a][b] = c;
adj[b][a] = c;
}
}
floyd();
result = 0;
for(int i=0; i<N; i++) {
st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
int c = Integer.parseInt(st.nextToken());
if( !update(a, b, c)) {
result++;
}
}
bw.flush();
bw.write(result + "\n");
}
bw.close();
}
public static void floyd() {
for(int i=0; i<V; i++) {
for(int j=0; j<V; j++) {
if(i==j) {
dist[i][j] = 0;
}else {
dist[i][j] = adj[i][j] != 0 ? adj[i][j] : Integer.MAX_VALUE;
}
}
}
for(int k=0; k<V; k++) {
for(int i=0; i<V; i++) {
for(int j=0; j<V; j++) {
if(dist[i][j] > dist[i][k] + dist[k][j]) {
dist[i][j] = dist[i][k] + dist[k][j];
}
}
}
}
}
public static boolean update(int a, int b, int c) {
if(dist[a][b] <= c) {return false;}
for(int x=0; x<V; x++) {
for(int y=0; y<V; y++) {
dist[x][y] = Math.min(dist[x][y], Math.min(dist[x][a]+c+dist[b][y], dist[x][b]+c+dist[a][y]));
}
}
return true;
}
}
마지막에 헤맸던 부분은 '두 도시간에 연결된 간선은 하나'라는 조건이 명시돼 있지 않다는 것이다. 다시말해 두 도시간에는 복수개의 간선이 있을 수 있고, 최소 비용의 간선을 골라서 넣어야한다.
'[개발] 지식 > 알고리즘 문제풀이' 카테고리의 다른 글
[문제][알고스팟] 근거리네트워크 (LAN) (1) (0) | 2018.06.06 |
---|---|
[문제][알고스팟] EDITORWARS (에디터 전쟁) (0) | 2018.05.27 |
[문제] 감시 카메라 설치 (GALLERY) (0) | 2017.11.11 |
[문제] SORTGAME (0) | 2017.10.13 |
벨만-포드 알고리즘 (0) | 2017.09.20 |
<