题目很简单,直接用Dijkstra求最短路,但是又有点变化,就是要再求路径的同时求出费用。当然,也不难,直接结构体,把费用与路径同时做计算。就可以得出最短路径跟费用了。记住:要考虑当最短路相同时,费用要选择最小的那一个。
郁闷的是,题目还有可能会输入同一条边得不同路径长度。
(1<n<=1000, 0<m<100000, s != t)
ps:
1、单向还是双向图,考虑清楚
2、注意那个maxInt这个值超不超,够不够
3、注意是否两点间有多条路径
4、分清变量是double型的还是int型的
5、注意主函数中初始化map[][]中的点边不要搞错(注意所有初始化,正确命名好变量)
仔细看好题目的input要求,a,b,d,p表示a和b之间有一条边。也就是说存在3,5,6,7,和3,5,13,34这种情况。还有,点的总数就n个,可是输入m却可以最多是100000,比n最多打了100倍,早该考虑到会有重边这种情况。有3,5,6,7,和3,5,13,34的可能,那么就应该有3,5,6,7,和3,5,6,34的存在啊。可是不考虑这里也可以ac.奇怪了.是HDU测试数据木有考虑到?
ac代码:
#include<iostream>
#define N 1009
#define Max 1000001;
using namespace std;
struct CP
{
int d;
int p;
} map[N][N];
struct AN
{
int d1;
int p1;
} dis[N];
int dijkstra(int s,int n,int e)//这里还是传统的dijkstra,就是加了结构体,还有计算最短路的价值
{
int visited[N],index=0;
int i,j;
memset(visited,0,sizeof(visited));
visited[s]=1;
for(i=1; i<=n; i++)
{
dis[i].d1=map[s][i].d;//路程
dis[i].p1=map[s][i].p;//费用
/// cout<<dis[i].p1<<" ";
}
for(i=1; i<n; i++)
{
int min=Max;
for(j=1; j<=n; j++)
{
if(visited[j]==0&&min>dis[j].d1)
{
min=dis[j].d1;
index=j;
}
}
visited[index]=1;
for(j=1; j<=n; j++)
{
if(visited[j]==0&&min+map[index][j].d<dis[j].d1)
{
dis[j].d1=min+map[index][j].d;
dis[j].p1=dis[index].p1+map[index][j].p;
}
else if(visited[j]==0&&min+map[index][j].d==dis[j].d1) //容易混淆,要仔细想
{
if(dis[j].p1>dis[index].p1+map[index][j].p)
dis[j].p1=dis[index].p1+map[index][j].p;
}
}
}
/* for(i=1;i<=n;i++)
cout<<dis[i].d1<<" ";
cout<<endl;
for(i=1;i<=n;i++)
cout<<dis[i].p1<<" ";
cout<<endl;*/
printf("%d %d\n",dis[e].d1,dis[e].p1);
return 0;
}
int main(void)
{
int n,m,i,j,a,b,d,p,s,e;
while(scanf("%d%d",&n,&m),n||m)
{
for(i=0; i<N; i++)
{
for(j=0; j<N; j++)
{
map[i][j].d=Max;
map[i][j].p=0;//初始费用为0或者Max都没关系,因为最后会被你输入覆盖。或者此路不存在,然后路劲为1000001
}
map[i][i].d=0;
}
for(i=1; i<=m; i++)
{
scanf("%d%d%d%d",&a,&b,&d,&p);
if(map[a][b].d>d) //晕,还有一条边,然后有两种不同长度的情况。郁闷中~为此WA了10次,郁闷了3天
{
map[a][b].d=map[b][a].d=d;
map[a][b].p=map[b][a].p=p;
}
else if(map[a][b].d==d)
{
if(map[a][b].p>p)
{
map[a][b].p=map[b][a].p=p;
}
}
}
scanf("%d%d",&s,&e);
dijkstra(s,n,e);
}
return 0;
}