原题网址:http://poj.org/problem?id=2457
题意:给出n条路 每条路的边权为1 求从1走到k要经过的最少的点的个数 并输出路径
最少点的个数 其实就是最短路径+1 所以我们可以把源点从1 向前移动一个单位 设为0
那么怎么去记录路径呢?
这里我们可以去开一个数组 记录当前这个点是由哪个点过来的
那么可以一直回溯 回溯到这个数组的初始化
等等 这是不是有点并查集的思想呢?
是的 确实是并查集找父节点的思想 那么我们只要把这个数组初始化 pre[i]=i 并在dijkstra中记录该点的父节点即可
#include<iostream>
#include<vector>
#include<cstdio>
#include<queue>
using namespace std;
typedef long long ll;
struct node
{
int from,to,cost;
node() {}
node(int t,int q,int w):from(t),to(q),cost(w) {}
friend bool operator <(const node &a, const node &b)
{
return a.cost>b.cost;
}
};
vector<node> v[1005];
bool vis[1005];
int pre[1005];
int dis[1005];
void dijkstra(int y)
{
priority_queue<node>q;
q.push(node(0,1,1));///因为要输出的是点的个数 那么我们可以把0设为源点
while(q.size())
{
node now=q.top();
q.pop();
if(!vis[now.to])
{
vis[now.to]=1;
///下面这里十分关键 也是容易错的地方
///dis和pre的赋值一定要在这里 原因的话请读者仔细思考
pre[now.to]=now.from;///记录当前点的父节点
dis[now.to]=now.cost;
for(int i=0; i<v[now.to].size(); i++)
{
node next=now;
next.to=v[now.to][i].to;
if(!vis[next.to])
{
next.from=now.to;
next.cost+=v[now.to][i].cost;
q.push(next);
}
}
}
}
if(dis[y]==~0u>>1)
puts("-1");
else
{
cout<<dis[y]<<endl;
vector<int>b;
while(pre[y]!=y)///存路径
b.push_back(y),y=pre[y];
for(int i=b.size()-1; i>=0; i--)///因为路径从父节点开始走的 倒着输出
cout<<b[i]<<endl;
}
}
int main()
{
int n,k;
while(cin>>n>>k)
{
for(int i=0; i<=1005; i++)
v[i].clear(),vis[i]=0,pre[i]=i,dis[i]=~0u>>1;
int a,b;
for(int i=1; i<=n; i++)
{
cin>>a>>b;
v[a].push_back(node(a,b,1));
}
dijkstra(k);
}
return 0;
}