这个题做了一个下午,刚开始用Java写,
<span style="font-size:14px;">import java.util.*;
public class Main {
static int INF = 99999999;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int M = sc.nextInt();
int start = sc.nextInt();
int end = sc.nextInt();
int[][] d = new int[N][N];
int[][] c = new int[N][N];
for(int i=0; i<N; i++)
for(int j=0; j<N; j++) {
d[i][j] = INF;
c[i][j] = INF;
}
for(int i=0; i<M; i++) {
int c1 = sc.nextInt();
int c2 = sc.nextInt();
int d1 = sc.nextInt();
int cc = sc.nextInt();
d[c1][c2] = d1;
d[c2][c1] = d1;
c[c1][c2] = cc;
c[c2][c1] = cc;
}
boolean[] marked = new boolean[N];
int[] dist = new int[N];
for(int i=0; i<N; i++)
dist[i] = d[start][i];
int[] cost = new int[N];
for(int i=0; i<N; i++)
cost[i] = c[start][i];
int[] prev = new int[N];
marked[start] = true;
dist[start] = 0;
cost[start] = 0;
int newP = start;
while(newP != end) {
for(int i=0; i<N; i++) {
if(!marked[i] && d[newP][i] < INF) {
if(dist[newP] + d[newP][i] < dist[i]) {
dist[i] = dist[newP] + d[newP][i];
cost[i] = cost[newP] + c[newP][i];
prev[i] = newP;
} else if(dist[newP] + d[newP][i] == dist[i]) {
if(cost[newP] + c[newP][i] < cost[i]) {
cost[i] = cost[newP] + c[newP][i];
prev[i] = newP;
}
}
}
}
int min = INF;
for(int i=0; i<N; i++) {
if(!marked[i] && dist[i] < min) {
min = dist[i];
newP = i;
}
}
marked[newP] = true;
}
StringBuilder sb = new StringBuilder();
int t = end;
while(t != start) {
sb.insert(0, t + " ");
t = prev[t];
}
sb.insert(0, start + " ");
sb.append(dist[end]);
sb.append(" " + cost[end]);
System.out.println(sb);
}
}</span><span style="font-size:24px;">
</span>
提示内存超了,改用C++写,还是超了,然后参考了别人的博客,PAT 1030. Travel Plan (30) (最短路),算法思路都差不多,但是它可以AC,好吧,那我就一点一点的改成你的样子,然而几个小时之后终于在它的输出上看出来了问题所在。。。。
输出我写的循环条件是
<span style="font-size: 14px;">while(t != start)</span>
而实际上在Dijkstra初始化时
<span style="font-size: 14px;"><span style="font-size:24px;">marked[start] = true;</span></span>
所以在第一次循环的时候下面的语句是不会被执行的
<span style="font-size: 14px;"><span style="font-size:24px;"><span style="font-size:24px;">prev[i] = newP;</span></span></span>
所以造成的结果是一直在死循环,一直往StringBuilder中append数据,所以最终要么超时,要么内存超限。但是也不能用默认赋值的0,因为节点就是从0开始的,可能会导致提前退出循环。
修改了之后,终于AC。。。。
<span style="font-size:14px;">package p1030;
import java.util.*;
public class Main {
static int INF = 99999999;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int M = sc.nextInt();
int start = sc.nextInt();
int end = sc.nextInt();
int[] prev = new int[N];
int[][] d = new int[N][N];
int[][] c = new int[N][N];
for(int i=0; i<N; i++) {
prev[i] = -1;
for(int j=0; j<N; j++) {
d[i][j] = INF;
c[i][j] = INF;
}
}
for(int i=0; i<M; i++) {
int c1 = sc.nextInt();
int c2 = sc.nextInt();
int d1 = sc.nextInt();
int cc = sc.nextInt();
d[c1][c2] = d1;
d[c2][c1] = d1;
c[c1][c2] = cc;
c[c2][c1] = cc;
}
boolean[] marked = new boolean[N];
int[] dist = new int[N];
for(int i=0; i<N; i++)
dist[i] = d[start][i];
int[] cost = new int[N];
for(int i=0; i<N; i++)
cost[i] = c[start][i];
marked[start] = true;
dist[start] = 0;
cost[start] = 0;
int newP = start;
while(newP != end) {
for(int i=0; i<N; i++) {
if(!marked[i] && d[newP][i] < INF) {
if(dist[newP] + d[newP][i] < dist[i]) {
dist[i] = dist[newP] + d[newP][i];
cost[i] = cost[newP] + c[newP][i];
prev[i] = newP;
} else if(dist[newP] + d[newP][i] == dist[i]) {
if(cost[newP] + c[newP][i] < cost[i]) {
cost[i] = cost[newP] + c[newP][i];
prev[i] = newP;
}
}
}
}
int min = INF;
for(int i=0; i<N; i++) {
if(!marked[i] && dist[i] < min) {
min = dist[i];
newP = i;
}
}
marked[newP] = true;
}
StringBuilder sb = new StringBuilder();
int t = end;
while(t != -1) {
sb.insert(0, t + " ");
t = prev[t];
}
sb.insert(0, start + " ");
sb.append(dist[end]);
sb.append(" " + cost[end]);
System.out.println(sb);
}
}
</span>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <stack>
using namespace std;
const int MAX = 501;
const int INF = 999999999;
int N, M, start, t, c1, c2, d1, cc, i, j;
int d[MAX][MAX], c[MAX][MAX];
int marked[MAX];
int dist[MAX], cost[MAX], pre[MAX];
vector<int> v;
stack<int> path;
int main()
{
//for(int i=0; i<MAX; i++)
//printf("%d ", &marked[i]);
scanf("%d %d %d %d", &N, &M, &start, &t);
for(i=0; i<N; i++) {
//marked[i] = 0;
pre[i] = -1;
for(j=0; j<N; j++) {
d[i][j] = INF;
c[i][j] = INF;
}
}
for(i=0; i<M; i++) {
scanf("%d %d %d %d", &c1, &c2, &d1, &cc);
d[c1][c2] = d1;
d[c2][c1] = d1;
c[c1][c2] = cc;
c[c2][c1] = cc;
}
for(i=0; i<N; i++) {
dist[i] = d[start][i];
cost[i] = c[start][i];
}
marked[start] = 1;
dist[start] = 0;
cost[start] = 0;
int newP = start;
while(newP != t) {
for(i=0; i<N; i++) {
if(marked[i] == 0 && d[newP][i] < INF) {
if(dist[newP] + d[newP][i] < dist[i]) {
dist[i] = dist[newP] + d[newP][i];
cost[i] = cost[newP] + c[newP][i];
pre[i] = newP;
} else if(dist[newP] + d[newP][i] == dist[i]) {
if(cost[newP] + c[newP][i] < cost[i]) {
cost[i] = cost[newP] + c[newP][i];
pre[i] = newP;
}
}
}
}
int min_dist = INF;
for(i=0; i<N; i++) {
if(marked[i] == 0 && dist[i] < min_dist) {
min_dist = dist[i];
newP = i;
}
}
marked[newP] = 1;
}
int p = pre[t];
while(p!=-1){
path.push(p);
p = pre[p];
}
printf("%d",start);
while(!path.empty()){
printf(" %d",path.top());
path.pop();
}
printf(" %d",t);
printf(" %d %d\n",dist[t],cost[t]);
}