![](/img/trans.png)
[英]How to generate a map of weighted graph for Dijkstra’s Shortest Path Algorithm from a text file in Java?
[英]Dijkstra algorithm in weighted graph in Java with big graph
我的任務是編寫一個程序,計算加權圖中從節點A(起點)到節點B(終點)所需的最短時間(我正在使用dijkstra算法)。 時間要求為2秒,內存限制為64 MB,我可以假定輸入的數據有效
第一行有4個整數:
節點數M(2≤M≤20000)
邊(連接)數量N(0≤N≤50000)
起始節點A(0≤A <M),結束節點O(0≤O <M)。
接下來的N行具有以三個整數表示的連接信息:
連接的計算機及其之間的時間,以毫秒(邊緣權重)為單位。 我的代碼未通過所有測試。 如果我用一個大圖測試我的代碼,那么它將失敗,因為堆內存用完了(我的機器上大約900MB)。
我的問題 :如何優化代碼以使其符合要求?
使用鄰接表就足夠了嗎?
我的代碼是這樣的:
import java.util.ArrayList;
import java.util.Scanner;
public class Route3 {
public static int minDistance(ArrayList<Long> mindist, ArrayList<Boolean> visited){
long min = Long.MAX_VALUE;
int minindex = -1;
for (int i = 0; i < mindist.size(); i++) {
if(!visited.get(i) && (mindist.get(i) <= min)) {
min = mindist.get(i);
minindex = i;
}
}
return minindex;
}
public static long dijkstra(long[][] graph, int start, int end) {
int computers = graph.length;
ArrayList<Boolean> traversed = new ArrayList<>(); //Hold traversed nodes
for (int i = 0; i < computers; i++) {
traversed.add(i,false);
}
ArrayList<Long> mindist = new ArrayList<>(); //Holds mindistances to nodes based on index
for (int i = 0; i < computers; i++) {
mindist.add(i,Long.MAX_VALUE);
}
mindist.set(start,(long)0);
for (int i = 0; i < computers; i++) {
int min = minDistance(mindist,traversed);
if(min == -1) return mindist.get(end);
traversed.set(min,true);
if(min == end) return mindist.get(min) == Long.MAX_VALUE ? -1 : mindist.get(min); //Error check
for (int j = 0; j < computers; j++) {
if(!traversed.get(j) && graph[min][j] != 0 && mindist.get(min) + graph[min][j] < mindist.get(j)) {
mindist.set(j,(mindist.get(min) + graph[min][j]));
}
}
}
return mindist.get(end) == Long.MAX_VALUE ? -1 : mindist.get(end);
}
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int computers = in.nextInt(); //nodes
int connections = in.nextInt(); //edges
int start = in.nextInt();
int end = in.nextInt();
long[][] graph = new long[computers+1][computers+1];
for (int i = 0; i < connections; i++) {
int x = in.nextInt();
int y = in.nextInt();
long t = in.nextLong();
graph[x][y] = t;
graph[y][x] = t;
}
if(connections == 0) {
System.out.println(-1);
System.exit(0);
}
long dist = dijkstra(graph,start,end);
if(dist != -1) System.out.println(dist);
else System.out.println(-1);
}
}
感謝所有幫助!
我認為您必須找到一種更好的方法來保存圖形信息。 這行:
long[][] graph = new long[computers+1][computers+1]
最多可能占用20001 * 20001 * 8個字節,即3GB!
由於您的網絡每個節點的連接數很少,因此建議將圖形存儲為連接的HashMaps的HashMap:
class Connection {
int nodeA, nodeB;
long time;
}
HashMap<Integer, HashMap<Integer, Connection>> graph;
聽起來效率較低,但是您要保存所有空白邊緣。 然后將Connection添加到由兩個節點(nodeA和nodeB)索引的圖形中:
void addConnection(Connection c)
{
HashMap<Integer, Connection> subgraph = graph.get(c.nodeA);
if(subgraph == null)
subgraph = new HashMap<>();
subgraph.put(c.nodeB, c);
HashMap<Integer, Connection> subgraph = graph.get(c.nodeB);
if(subgraph == null)
subgraph = new HashMap<>();
subgraph.put(c.nodeA, c);
}
並檢索連接描述符,例如:
long getConnection(int nodeA, int nodeB)
{
ArrayList<Connection> subgraph = graph.get(nodeA);
if(subgraph == null)
return 0L;
Connection c = subgraph.get(nodeB);
if(c == null)
return 0L;
return c.time;
}
這將使您的程序變慢,但內存效率更高。
警告:該代碼未經測試,僅供參考。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.