http://poj.org/problem?id=2457
Part Acquisition部分收购
题意:奶牛们被送往太空去执行一个任务:为它们的农场收购一台挤奶机器。它们正通过
一个含有N颗行星的星系。(1<=N<=50 000),每颗行星都是一个交易站。
奶牛们决定了使用 K种(1<=K<=1000)种商品在这些星球中进行交易。这些星球没
有发展货币,所以星球交易都是在货易系统下工作的:所有的交易都是用一种货物交换
另外一种货物。假设互相交易的两种货物是不同的。
奶牛们从地球出发,带着一罐高品质的干草(货物1号),它们想最终用罐干草换回
一台挤奶机器(货物K号)。你们经常喝奶牛们的牛奶,奶牛们请你帮忙:确定如何与
该星系所有星球交易,最后得到得到货物K号,奶牛们要你构造最好的交易序列。如果无
论如何都不可能最后换得货物K号,那么输出“-1”。
Input 输入
* 第一行:N和K
* 第 2..N+1行: 第 i+1 行 包含两个整数 ai 和 bi, 代表星球i用货物ai去换取货物bi.
Output 输出
* 第一行: 一个整数T,即为用货物1号换得货物k号的最少交换序列。(或者 -1。如果无法
换得货物K号 ).
* 第2..T+1行: 列出交换序列中每个货物的编号.
Sample Input
6 5
1 3
3 2
2 3
3 1
2 5
5 4
Sample Output
4
1
3
2
5
把货物当做节点,星球当做节点间的权为1的边,而这题我花的时间大部分在路径的记录上
思路:先建一个数组pre[MAXVEX],松弛操作时,便将当前节点i的前驱节点j记下pre[i]=j。
因为SPFA已证明最短路上的起点到任意一点的路都为最短。所以SPFA后,得出的数组pre中
的元素j,便是起点到节点i最短路径上的前驱...(有点难表达....image...image)
最后的路径输出(需要注意),可以新建一个数组读入再输入,或递归输出...
附:SPFA优化:SLF和LLL:SLF:Small Label First 策略,设要加入的节点是j,队首元素为i,若dist(j)<dist(i),则将j插入队首,否则插入队尾。 LLL:Large Label Last 策略,设队首元素为i,队列中所有dist值的平均值为x,若dist(i)>x则将i插入到队尾,查找下一元素,直到找到某一i使得dist(i)<=x,则将i出对进行松弛操作。 SLF 可使速度提高 15 ~ 20%;SLF + LLL 可提高约 50%。 在实际的应用中SPFA的算法时间效率不是很稳定,为了避免最坏情况的出现,通常使用效率更加稳定的Dijkstra算法。
代码如下:
#include<cstdio>
#include<cstring>
using namespace std;
#define INF 99999
#define MAXVEX 1005
#define MAXEDGE 50005
struct EdgeType{
int begin;
int end;
int next;
}edge[MAXEDGE]; /*数组实现邻接表*/
int n,k; /*n个星球,k个商品。商品看作节点,星球看作权值为1的边*/
int numE=0;
int last[MAXVEX],step[MAXVEX]; //step记录每个星球的最小交换次数
int pre[MAXVEX]; //previous point:每个节点的上一个
void read(){
int i;
scanf("%d %d",&n,&k);
memset(last,0,sizeof(last));
for (i=1;i<=n;i++){
int a,b;
numE++;
scanf("%d %d",&a,&b);
edge[numE].begin=a;edge[numE].end=b;
edge[numE].next=last[a];last[a]=numE;
}
}
void spfa(){
bool v[MAXVEX]={};
int que[MAXVEX],head=1,tail=2;
int i;
for (i=1;i<=k;i++) step[i]=INF;
v[1]=true;que[head]=1;step[1]=1;
while (head!=tail){
int x=que[head],l;
for (l=last[x];l>0;l=edge[l].next){
int y=edge[l].end;
if (step[x]+1<step[y]){
step[y]=step[x]+1;
pre[y]=edge[l].begin; /*记录每个点的前驱*/
if (!v[y]){
if (step[y]<step[x]) que[head--]=y; /*SLF优化*/
else {
que[tail]=y;
tail++;if (tail==MAXVEX)tail=1;
}
v[y]=true;
}
}
}/*for*/
head++;if (head==MAXVEX)head=1;
v[x]=false;
}/*while*/
}
void print_way(int now){
int ans;
if (now==1) ans=1;
else {
print_way(pre[now]);
ans=now;
}
printf("%d\n",ans);
}
int main(){
read();
spfa();
if (step[k]!=INF){
printf("%d\n",step[k]);
print_way(k);
}else printf("-1");
return 0;
}