http://pat.zju.edu.cn/contests/pat-a-practise/1030
输出两个城市间的最短路径值,路径经过的结点
使用dikstra算法,邻接表保存图,使用栈输出保存的路径
理解edge[i] 结点i的邻接链表,保存与i相邻接的边,边结构体保存next,cost,distance
理解路径:每当有更短路径经过newP到t,则path[t]=newP,所以0(s)----2----3(end)
由path[3]=2, 再path[2]=0,, path[0]=-1(初始化作为结束)
所以用栈保存,栈顶便是起始点,栈底便是结束点
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
struct E
{
int next;
int distance;
int cost;
};
vector<E> edge[510];
stack<int> ans;
int dis[510]; //到i的最短距离
int costSum[510]; //到i的最小耗费
bool mark[510];
int path[510]; //保存路径
void dij(int s,int e,int n)
{
int i,j;
dis[s]=0;
mark[s]=true;
int newP=s;
for (i=0;i<n-1;i++)
{
for (j=0;j<edge[newP].size();j++) //遍历newP的所有邻接点
{
int t=edge[newP][j].next; //得到所有边结构体数据
int di=edge[newP][j].distance;
int co=edge[newP][j].cost;
if (mark[t])
{
continue;
}
if (dis[t]==-1 || dis[t]>dis[newP]+di ) //更短距离
{
dis[t]=dis[newP]+di;
costSum[t]=costSum[newP]+co;
path[t]=newP; //记录经newP到t
}
if ( dis[t]==dis[newP]+di && costSum[t]>costSum[newP]+co )
{
costSum[t]=costSum[newP]+co;
path[t]=newP;
}
}
int min=123123;
for (j=0;j<n;j++) //找出现在最小边(未访问结点的)
{
if (mark[j])
{
continue;
}
if (dis[j]==-1)
{
continue;
}
if (dis[j]<min)
{
min=dis[j];
newP=j;
}
}
mark[newP]=true;
}
}
int main()
{
freopen("D:\\test.txt","r",stdin);
int n,m,s,e,i;
cin>>n>>m>>s>>e;
for (i=0;i<m;i++)
{
int a,b,c,d;
cin>>a>>b>>d>>c;
E tmp;
tmp.cost=c;
tmp.distance=d;
tmp.next=b;
edge[a].push_back(tmp);
tmp.next=a;
edge[b].push_back(tmp);
}
for (i=0;i<n;i++)
{
dis[i]=-1;
mark[i]=false;
path[i]=-1;
}
dij(s,e,n);
int x=e;
while (x!=-1) //路径上经过的点入栈
{
ans.push(x);
x=path[x];
}
while (!ans.empty()) //输出:从起始到结束
{
cout<<ans.top()<<" ";
ans.pop();
}
cout<<dis[e]<<" "<<costSum[e]<<endl;
return 0;
}