这个题疯狂RE.。。。。网上找的代码也不好使,不懂了。
无向图,数据量太大,开邻接矩阵会TLE。所以开邻接向量
先一次BFS,将每一个点的距离找出来。
第二次BFS,将以每一个点的距离为参照,先判断是否是最短路径(距离减1),然后再判断颜色。然后再对这个点所有最短路径且最小颜色的点BFS。注意还要把ans[i]设置为自动更新对应距离的最小颜色。
d[i]和mc设为-1,为初始值。
输出也可以参考一下
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn=200000+5;
//无向图
//数据量太大,开邻接矩阵会TLE。所以开邻接向量
vector <int> g[maxn];//g[i]储存的事第i个节点指向的边
vector <int> c[maxn];//g[i]储存的是第i个节点指向边对应的权重
int n,m,vis[maxn],d[maxn],ans[maxn];//vis用来储存是否遍历到,d储存各点的距离,ans储存答案的序列,从0到n-1顺序
void init(){
memset(vis,0,sizeof(vis));
memset(d,-1,sizeof(d));
memset(ans,0,sizeof(ans));
for(int i=0;i<=n;i++){
g[i].clear();
c[i].clear();
}
for(int i=0;i<m;i++){
int from,to,w;
scanf("%d %d %d",&from,&to,&w);
g[from].push_back(to);
g[to].push_back(from);
c[from].push_back(w);
c[to].push_back(w);
}
}
void bfs1(int n){
queue <int >q;
q.push(n);
d[n]=0;
while(!q.empty()){
int u=q.front();
q.pop();
int sz=g[u].size();
for(int i=0;i<sz;i++){//用d[i]==-1来巧妙判断这个节点是否被遍历过
int temp=g[u][i];
if(temp==1){
d[1]=d[u]+1;
return;
}
else if(d[temp]==-1){
d[temp]=d[u]+1;
q.push(temp);
}
}
}
return;
}
void bfs2(){
queue<int> q;
q.push(1);
while(!q.empty()){
int u=q.front();
q.pop();
if(u==n){//思考出口
return;
}
int mc=-1;//mc为最小颜色的目标节点的颜色
int sz=g[u].size();
for(int i=0;i<sz;i++){
int tg=g[u][i];
// printf("tg=%d d[tg]=%d ",tg,d[tg]);
if(d[tg]==d[u]-1){
if(mc==-1){
// printf("c[%d][%d]=%d\n",u,i,c[u][i]);
mc=c[u][i];
}
else if(mc>c[u][i]){
mc=c[u][i];
}
}
}
// printf("mc=%d\n",mc);
int t=d[1]-d[u];
if(ans[t]==0) ans[t]=mc;
else{
ans[t]=min(mc,ans[t]);//这个是为后面重新BFS服务的。第一次到这里的ans[t]都应该是0,但是后面会重新BFS。
}
for(int i=0;i<sz;i++){
int tg=g[u][i];
if(c[u][i]==mc&&d[tg]==d[u]-1){//满足条件 1.最短路径 2.最小颜色
q.push(tg);
// vis[tg]=1;
}
}
}
}
int main(void){
while(scanf("%d %d",&n,&m)){
init();
bfs1(n);
bfs2();
printf("%d\n",d[1]);
for(int i=0;i<d[1];i++){
if(i) printf(" ");
printf("%d",ans[i]);
}
printf("\n");
}
return 0;
}