uva 1599 ideal path(好题)——yhx
1 #include<cstdio> 2 #include<queue> 3 #include<stack> 4 #include<cstring> 5 using namespace std; 6 queue<int> q1,q2; 7 stack<int> s; 8 int first[100010],next[400010],to[400010],dis[100010]; 9 long long color[400010],ans[100010],pre_color[100010]; 10 bool vis[100010]; 11 int main() 12 { 13 int i,j,k,m,n,p,x,y; 14 long long min,z; 15 while(scanf("%d%d",&n,&m)==2) 16 { 17 memset(first,0,sizeof(first)); 18 memset(next,0,sizeof(next)); 19 memset(to,0,sizeof(to)); 20 memset(color,0,sizeof(color)); 21 memset(dis,0,sizeof(dis)); 22 memset(ans,0,sizeof(ans)); 23 memset(vis,0,sizeof(vis)); 24 for (i=1;i<=m;i++) 25 { 26 scanf("%d%d%lld",&x,&y,&z); 27 next[i]=first[x]; 28 first[x]=i; 29 to[i]=y; 30 color[i]=z; 31 next[i+m]=first[y]; 32 first[y]=i+m; 33 to[i+m]=x; 34 color[i+m]=z; 35 } 36 memset(dis,0x7f,sizeof(dis)); 37 dis[n]=0; 38 while (!q1.empty()) q1.pop(); 39 q1.push(n); 40 while (!q1.empty()) 41 { 42 x=q1.front(); 43 q1.pop(); 44 for (i=first[x];i;i=next[i]) 45 if (dis[x]+1<dis[to[i]]) 46 { 47 dis[to[i]]=dis[x]+1; 48 q1.push(to[i]); 49 } 50 } 51 memset(ans,0x7f,sizeof(ans)); 52 ans[0]=0; 53 while (!q2.empty()) q2.pop(); 54 q2.push(1); 55 while (!q2.empty()) 56 { 57 x=q2.front(); 58 q2.pop(); 59 if (pre_color[x]!=ans[dis[1]-dis[x]]) continue; 60 if (x==n) break; 61 if (vis[x]) continue; 62 vis[x]=1; 63 for (i=first[x];i;i=next[i]) 64 if (dis[to[i]]==dis[x]-1&&color[i]<ans[dis[1]-dis[to[i]]]) 65 ans[dis[1]-dis[to[i]]]=color[i]; 66 for (i=first[x];i;i=next[i]) 67 if (dis[to[i]]==dis[x]-1&&color[i]==ans[dis[1]-dis[to[i]]]) 68 { 69 q2.push(to[i]); 70 pre_color[to[i]]=ans[dis[1]-dis[to[i]]]; 71 } 72 } 73 printf("%d\n",dis[1]); 74 printf("%d",ans[1]); 75 for (i=2;i<=dis[1];i++) 76 printf(" %d",ans[i]); 77 printf("\n"); 78 } 79 }
所求路线有两个要求,一是距离最短,二是在一的前提下字母序最小。因此进行BFS时,需要同时顾及两个因素。
保证距离最短时,可以先从终点出发求一遍最短路,这样每次BFS时只要保证下一步的点的最短路比当前点小1,最后求出来的就一定是最短路。
处理字典序时,采用贪心策略,即从头开始每一步都要最小。对一个点操作时比较路线与已知答案,如果劣于已知答案直接舍去。
注意判重,不重复搜索某个点。