Ideal Path UVA - 1599

题目链接

这道题利用两次BFS来求解:

  1. 由于题目有两个限制条件:最短路径,字典序颜色,假设我们从后往前BFS,将得到每个节点到终点的步数,这样就知道起点到终点的步数,同时中间的路径也可以由每次递减来确定,第二次BFS中维护最小字典序即完成。
  2. 输入涉及到重复和自环,要避免重复和过滤自环。
  3. 由于数量级很大采用邻接表存储数据。

C++代码描述

#include<bits/stdc++.h> 
using namespace std;
const int maxn=100000;
const int inf=0x7fffffff;
int d[maxn],res[maxn];
bool vist[maxn],inqueue[maxn];
int n,m,v;

struct Node{
    int link,color;
    Node(int l,int c):link(l),color(c){}
};//节点定义
vector<Node> linklist[maxn];//邻接表定义 
void dfs(int start,int end){
    memset(inqueue,0,sizeof(inqueue));
    memset(vist,0,sizeof(vist));
    queue<int>  q;
    q.push(start);
    if(start){
        while(!q.empty()){
            int u=q.front();q.pop();vist[u]=1;
            for(int i=0;i<linklist[u].size();i++)
                if(!vist[v=linklist[u][i].link]&&!inqueue[v]){
                    d[v]=d[u]+1;
                    if(v==0)    return;
                    q.push(v);
                    inqueue[v]=1;
                }
        }
    }else{
        memset(res,0,sizeof(int)*n);
        while(!q.empty()){
            int u=q.front();q.pop();vist[u]=1;
            if(u==n-1)  return;
            int minc=inf;
            for(int i=0;i<linklist[u].size();i++)if(!vist[v=linklist[u][i].link]&&d[v]==d[u]-1)minc=min(minc,linklist[u][i].color);
            for(int i=0;i<linklist[u].size();i++)if(!vist[v=linklist[u][i].link]&&d[v]==d[u]-1&&!inqueue[v]&&linklist[u][i].color==minc)inqueue[v]=1,q.push(v);
            int index=d[0]-d[u];
            if(res[index]==0)   res[index]=minc;
            else    res[index]=min(res[index],minc);
        }
    }
}
int main(){
//  freopen("F://inp.txt","r",stdin);
    while(cin>>n>>m){
        for(int i=0;i<n;i++)    linklist[i].clear();
        memset(d,-1,sizeof(d));d[n-1]=0;
        while(m--){
            int a,b,c;
            cin>>a>>b>>c;
            if(a!=b){
                linklist[a-1].push_back(Node(b-1,c));
                linklist[b-1].push_back(Node(a-1,c));
            }
        }
        dfs(n-1,0);
        dfs(0,n-1);
        cout<<d[0]<<endl<<res[0];
        for(int i=1;i<d[0];i++) cout<<" "<<res[i];
        cout<<endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值