UVA1599 Ideal Path
问题描述:
给定一个无向联通图G,G中有N个顶点,M条边,每条边的长度为一个单位,并有一个整数表示这条边的颜色,求从1到N的最短路,如果有多个,则找出颜色字典序最小的路径。
思路:
从N开始进行一次BFS,对于一个节点y,记录y节点的距离dis[y]和对应到达y的边e=pre[y],由此,根据pre[y]可以回溯出N到y的路径。当某个节点y被再次访问时,并且新的距离和旧的距离相等(事实上,不存在第二次访问y时,距离更小或者更大的情况),表示N到y有了一条新的路径,此时借助之前保存的pre[j]信息和新的路径对比,保留字典序小的路径。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
typedef struct edge{
int x,y,c;
int nxt;
}edge;
edge buf[400000+20];
int head[100000+20];
int pre[100000+20];
int que[100000+20];
int dis[100000+20];
char vis[100000+20];
int cnt,top,tail;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n,m;
int i,j,k,x,y,c;
int st,ed;
while(cin>>n>>m){
cnt=1; st=1; ed=n; top=0;tail=0;
memset(head,0,sizeof(head));
memset(pre,0,sizeof(pre));
memset(dis,0,sizeof(dis));
memset(vis,0,sizeof(vis));
for(i=1,j=0;j<m;j++,i+=2){
cin>>x>>y>>c;
buf[i].x=x; buf[i].y=y; buf[i].c=c;
buf[i+1].x=y; buf[i+1].y=x; buf[i+1].c=c;
buf[i].nxt=head[x]; head[x]=i;
buf[i+1].nxt=head[y]; head[y]=i+1;
}
que[0]=ed; tail=1; pre[1]=pre[0]=0;
dis[ed]=0; vis[ed]=1;
while(top<tail){
x=que[top++];
for(j=head[x];j;j=buf[j].nxt){
y=buf[j].y; c=buf[j].c;
if(vis[y]){
if(dis[y]==dis[x]+1){ ///距离相等
//xx=x; yy=y;
int e1=pre[y],e2=j;
while(e1!=e2 && buf[e1].c==buf[e2].c){ ///两条路径一定会同时结束
e1=pre[buf[e1].x]; e2=pre[buf[e2].x];
}
if(buf[e1].c>buf[e2].c){
pre[y]=j;
}
}
}else{
vis[y]=1;
pre[y]=j;
dis[y]=dis[x]+1;
que[tail++]=y;
}
}
}
cout<<dis[st]<<endl;
for(int e=pre[st],i=0;i<dis[st];i++){
if(i) cout<<' ';
cout<<buf[e].c;
e=pre[buf[e].x];
}
cout<<endl;
}
return 0;
}