UVA1599-字典序+BFS
程序员文章站
2022-06-03 18:37:10
...
第一次写这么复杂的bfs,卡了我近一周,需要注意的细节很多,很多地方感觉跟题解差不多,但是就是不对。失之毫厘谬以千里啊。
这里是原题
这里是我当时看的一个比较好的题解(里面用的指针我不懂 但思路非常棒)
大概做法
先从n开始bfs,得到每个点到n的最短距离d[i]。然后从起点开始bfs,每一步保证d[v]=d[u]-1,同时储存最小字典序
代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#define maxn 100005
using namespace std;
typedef struct edge{
int col,to;
edge(int a,int b):to(a),col(b){}
}Edge;
vector <Edge>e[maxn]; //邻接表储存图
int n,m,u,v,c,d[maxn],ans[maxn*4];//uvc是临时变量 个人习惯
bool vis[maxn];
void init()
{
memset(ans,0x3f,sizeof ans);
memset(d,-1,sizeof d);
memset(vis,0,sizeof vis);
for (int i=1;i<=n;i++)e[i].clear();
for(int i=1;i<=m;++i){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(a==b)continue;
e[a].push_back(edge(b,c));
e[b].push_back(edge(a,c)); //双向边
}
return ;
}
void fbfs(){
queue<int >q;
q.push(n);
d[n]=0;
while(!q.empty()){
u=q.front();
q.pop();
// if(u==1){return ;}这里建议大家把图遍历全,不要贪图那一点点时间,不然会出现玄学bug
for(int i=0,len=e[u].size();i<len;++i){
v=e[u][i].to;
if(d[v]!=-1)continue;//不重复访问 写过复杂图bfs的应该都懂
d[v]=d[u]+1;
q.push(v);
}
}
return ;
}
void bfs(){
/*
这个题有一点很重要,需要先在这里说明,一不能简单更新ans(见图2),二每个点会入队多遍但只会访问一遍(见题中样例,如果每个点只入队一遍就会错过后来的更优解)
这些在我下面的代码里都有所体现
*/
queue<pair<int,int> >q; //这里很秒 first 储存节点编号,second储存访问到达这个节点的边的颜色 我也是看别人代码学会的
q.push(make_pair(1,0));
ans[0]=0;//
while(!q.empty()){
u=q.front().first;
c=q.front().second;
q.pop();
if(ans[d[1]-d[u]]!=c||u==n||vis[u])continue;
//一满足沿着最短路线走 二别走过 三只访问一遍即可
vis[u]=1;
for(int i=0,len=e[u].size();i<len;++i){
v=e[u][i].to;
c=e[u][i].col;
if(d[u]!=d[v]+1||c>=ans[d[1]-d[v]])continue;
ans[d[1]-d[v]]=c;//更新第(d[1]-d[v])步最小颜色
}
for(int i=0,len=e[u].size();i<len;++i){
v=e[u][i].to;
c=e[u][i].col;
if(d[u]!=d[v]+1||c!=ans[d[1]-d[v]])continue; //如果有多个当前最优解 把他们全部入队
q.push(make_pair(v,c));
}
//有可能当前阶段有多个解能到达点i,但到达点i的路径颜色不同或相同,这时就会通过开头的剪枝,将他们去掉 因为将该层遍历完后一定能得到最优解的颜色 就可以通过比较ans[]只访问最优解, 并通过vis只访问一次最优解
}
}
int main(){
while(scanf("%d%d",&n,&m)==2){
init();
fbfs();//从n开始
bfs();//从1开始
printf("%d\n", d[1]);
for (int i = 1; i<=d[1]; i++)
printf("%d%c",ans[i],i==d[1]?'\n':' ');
}
return 0;
}
下一篇: sqlserver 实现字符串的聚合