题目地址:点击打开链接
思路:更新距离的时候把时间也更新一下就行,总结一下图论类的题的各种坑吧,1建图的时候除非说明是单向图,否则建双向图,2有重边的可能,记得与以前的比较,3有可能起点和终点是一个点,wrong了无数发,把自己的代码一点一点嵌到被人的代码试,结果是变量名写错了,害我调了2小时,都是泪啊,还有就是求最短路的时候,Dijkstra算法必须都运行完,因为后面加进来的一个点有可能会把前面已经求出来的最短路径更新的还短,我以前写过知道了终点的最短路直接退出来的Dijkstra代码,却能AC,其实不能退出来,经学长一指点,原来那道题终点就是标号最大的一个,所以造成退出来和不退出来效果都一样
AC代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <cstring>
#include <climits>
#include <cmath>
#include <cctype>
using namespace std;
const int zui = 0x7fffffff;
const int maxn = 1010;
int n,m;
int dist[maxn][maxn],cost[maxn][maxn],visit[maxn];
int lowdist[maxn],lowcost[maxn];
int start,end1;
void Dijkstra()
{
int i,j,k,min2;
memset(visit,0,sizeof(visit));
for(i=1; i<=n; i++)
{
lowdist[i] = dist[start][i];
lowcost[i] = cost[start][i];
}
visit[start] = 1;
for(i=1; i<n; i++)
{
min2 = zui;
for(j=1; j<=n; j++)
{
if(!visit[j] && lowdist[j] < min2)
{
min2 = lowdist[j];
k = j;
}
}
visit[k] = 1;
for(j=1; j<=n; j++)
{
if(!visit[j] && dist[k][j] < zui)
{
if(lowdist[k] + dist[k][j] < lowdist[j])
{
lowdist[j] = lowdist[k] + dist[k][j];
lowcost[j] = lowcost[k] + cost[k][j];
}
else if(lowdist[k] + dist[k][j] == lowdist[j])
{
if(lowcost[k] + cost[k][j] < lowcost[j])
{
lowcost[j] = lowcost[k] + cost[k][j];
}
}
}
}
}
}
int main()
{
int i,j;
int a,b,d,p;
while(scanf("%d%d",&n,&m))
{
if(n + m == 0)
break;
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
dist[i][j] = zui;
cost[i][j] = zui;
}
}
for(i=1; i<=m; i++)
{
scanf("%d%d%d%d",&a,&b,&d,&p);
if(d < dist[a][b])
{
dist[a][b] = dist[b][a] = d;
cost[a][b] = cost[b][a] = p;
}
else if(d == dist[a][b])
{
if(p < cost[a][b])
{
cost[a][b] = cost[b][a] = p;
}
}
}
scanf("%d%d",&start,&end1);
Dijkstra();
printf("%d %d\n",lowdist[end1],lowcost[end1]);
}
return 0;
}
错误代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <cstring>
#include <climits>
#include <cmath>
#include <cctype>
using namespace std;
const int zui = 1000000000;
const int maxn = 1010;
int n,m,start,end1;
int dis[maxn][maxn],cost[maxn][maxn];
int lowcost1[maxn],lowcost2[maxn],visit[maxn];
void Dijkstra()
{
memset(visit,0,sizeof(visit));
int i,j,k;
for(i=1; i<=n; i++)
{
lowcost1[i] = dis[start][i];
lowcost2[i] = cost[start][i];
}
visit[start] = 1;
for(i=1; i<n; i++)
{
int min1 = zui - 10;
for(j=1; j<=n; j++)
{
if(visit[j] == 0 && lowcost1[j] <= min1)
{
if(lowcost1[j] < min1)
{
min1 = lowcost1[j];
k = j;
}
else if(lowcost1[j] == min1)
{
if(lowcost2[j] < lowcost2[k])
{
k = j;
}
}
}
}
visit[k] = 1;
if(k == end1)
return;
for(j=1; j<=n; j++)
{
if(visit[j] == 0 && lowcost1[k] + dis[k][j] < lowcost1[j])
{
lowcost1[j] = lowcost1[k] + dis[k][j];
lowcost2[j] = lowcost2[k] + cost[k][j];//花的钱也要改过来
}
}
}
}
int main()
{
int i,j;
int a,b,d,p;
while(scanf("%d%d",&n,&m))
{
if(n + m == 0)
break;
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
dis[i][j] = zui;
cost[i][j] = zui;
}
}
for(i=1; i<=m; i++)
{
scanf("%d%d%d%d",&a,&b,&d,&p);
if(d < dis[a][b])
{
dis[a][b] = dis[b][a] = d;
cost[a][b] = cost[b][a] = p;
}
else if(d == dis[a][b])
{
if(p < cost[a][b])
{
cost[a][b] = cost[b][a] = p;
}
}
}
scanf("%d%d",&start,&end1);
Dijkstra();
printf("%d %d\n",lowcost1[end1],lowcost2[end1]);
}
return 0;
}
刚开始思维比较混乱,写了这破代码,看了别人的题解才知道,我这个思路就是错的,我只更新路径小的时候的钱数,却不更新路径相同的时候的钱数,而是在查找里面找路径相同且钱数最低的,我只是求的顺序变了一下,却没把钱数更新过来
在Dijkstra算法里面记得把2个j的for循环语句套到i的循环语句里面,刚开始这也错了