/*
复杂图的bfs
本题需要注意的是寻找颜色最短的情况下的字典序最小的路径,走的一定是最短路径。
直接bfs的话,每次走颜色最小的边,遇到的问题是,以题例来说,当1 2 3入队后,需要在从
2 3出发的所有边中选出颜色最小的(这其实又是一次bfs),不能遇到4就结束掉。
值此困难,笔者还是选择两次bfs的常规解决方案。
1)第一遍bfs求出每个点到n的最短路径长度,维护一个dis数组
2)第二遍bfs走路,利用dis数组统计最小颜色字典序路径
注意一定要结合具体的图,这样可以发现问题,也利于编程。
*/
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100000+5;
const int inf=1000000000+5;
int n,m;
struct node{
int to,cor;
node(int t,int c):to(t),cor(c){}
};
vector<node>vec[maxn];
int vis[maxn];
int ans[maxn];
int dis[maxn];
void anti_bfs(){
memset(vis,0,sizeof(vis));
queue<int>que;
que.push(n); dis[n]=0;
vis[n]=1;
while(!que.empty()){
int u=que.front(); que.pop();
for(int i=0;i<vec[u].size();i++){
if(vis[vec[u][i].to]==0){
dis[vec[u][i].to]=dis[u]+1;
que.push(vec[u][i].to);
vis[vec[u][i].to]=1;
}
}
}
}
void bfs(){
memset(vis,0,sizeof(vis));
memset(ans,0,sizeof(ans));
queue<int>que;
que.push(1);
vis[1]=1;
while(!que.empty()){
int u=que.front(); que.pop();
int mmin=inf;
//选出颜色最小的
for(int i=0;i<vec[u].size();i++){
if(dis[u]-1==dis[vec[u][i].to]) //注意结合具体图考虑到这一点
mmin=min(mmin,vec[u][i].cor);
}
int tmp=dis[1]-dis[u];
if(ans[tmp]==0) ans[tmp]=mmin;
else ans[tmp]=min(ans[tmp],mmin);
//把满足要求的结点入队
for(int i=0;i<vec[u].size();i++){
int v=vec[u][i].to;
if(!vis[v] && dis[v]+1==dis[u] && vec[u][i].cor==mmin){
que.push(v);
vis[v]=1;
}
}
}
}
int main()
{
while(cin>>n>>m){
int x,y,c;
for(int i=0;i<maxn;i++)
vec[i].clear();
for(int i=0;i<m;i++){
cin>>x>>y>>c;
if(x!=y){ //把自身环可以直接去掉,减少后续bfs时间,当然不去掉也OK
vec[x].push_back(node(y,c));
vec[y].push_back(node(x,c));
}
}
anti_bfs();
bfs();
cout<<dis[1]<<endl;
for(int i=0;i<dis[1];i++){
if(i) cout<<" "<<ans[i];
else cout<<ans[i];
}
cout<<endl;
}
return 0;
}
紫书第六章-----数据结构基础(例题6-20 Ideal Path UVA - 1599 )
最新推荐文章于 2020-01-06 21:07:45 发布