1 条题解

  • 0
    @ 2026-10-19 1:02:37

    [NOI 1997] 最优乘车

    知识点

    图建模、广度优先搜索、最少换乘

    解题思路

    对每条单向线路,将前面的每站向后面的每站连一条边,表示乘一辆车可达。原站1做BFS,得到最少乘车次数,到终点后减1即换乘次数;不可达输出NO。

    正确性说明

    一次合法乘车对应某线路由较早站到较晚站,恰与一条建模边对应;反之每条边都能用一辆车实现。故图中边数最短路等于最少乘车次数。至少乘一次才能由1到不同终点N,因此减1恰为换乘数。

    易错点

    线路单向,不能逆走;输入每条线路长度不固定,按整行读取;一车经过多站也只算一次乘车。

    复杂度

    N站、各线路长度Li,建图O(ΣLi²),矩阵BFS O(N²),空间O(N²),N≤500。

    参考代码(GNU C++17)

    #include<bits/stdc++.h>
    using namespace std;
    int main(){ios::sync_with_stdio(false);cin.tie(nullptr);int M,N;cin>>M>>N;string line;getline(cin,line);vector<vector<char>>g(N+1,vector<char>(N+1));for(int z=0;z<M;z++){getline(cin,line);stringstream ss(line);vector<int>a;int x;while(ss>>x)a.push_back(x);for(int i=0;i<(int)a.size();i++)for(int j=i+1;j<(int)a.size();j++)g[a[i]][a[j]]=1;}vector<int>d(N+1,-1);queue<int>q;d[1]=0;q.push(1);while(!q.empty()){int u=q.front();q.pop();for(int v=1;v<=N;v++)if(g[u][v]&&d[v]<0)d[v]=d[u]+1,q.push(v);}if(d[N]<0)cout<<"NO\n";else cout<<d[N]-1<<'\n';}
    
    • 1

    信息

    ID
    870
    时间
    1000ms
    内存
    128MiB
    难度
    普及
    标签
    递交数
    0
    已通过
    0
    上传者