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;
}