1 条题解

  • 0
    @ 2026-10-18 21:19:18

    [CSP-J 2019] 加工零件

    知识点

    无向图、奇偶性、分层图、广度优先搜索

    解题思路

    沿生产需求回溯L层,需要1号工人提供原料,当且仅当从a到1存在长度恰为L的游走。无向图允许重复经过边;若已有同奇偶长度的游走,可沿任意一条经过的边往返,使长度每次增加2。因此从1号点对“顶点、长度奇偶”二层状态做BFS,得到每个点到1的最短奇长度和最短偶长度。查询检查相应奇偶的距离是否不超过L。若1号点完全孤立,任何正L都不可能,单独判No。

    正确性说明

    BFS在状态图中跨一条原图边同时翻转奇偶,故求出的d[a][L mod 2]是对应奇偶游走的最短长度。若存在长度L的游走,则这个最短长度必不大于L;反之,若最短长度不大于L,两者同奇偶,其差为非负偶数,可通过往返同一条边补足。最短距离为0且需要延长时,1号点至少有一条邻边才能往返,代码显式排除孤立点,故判定充分且必要。

    易错点

    这里是游走而非简单路径;同一顶点要记录两种奇偶状态;不能只求普通最短路。图可能不连通,未访问状态为-1,不能按负数≤L误判。输出Yes/No大小写与原题一致。

    复杂度

    时间O(n+m+q),空间O(n+m),每次查询O(1)。

    参考代码(GNU C++17)

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
        ios::sync_with_stdio(false); cin.tie(nullptr);
        int n,m,q; cin>>n>>m>>q;
        vector<vector<int>> g(n+1);
        for(int i=0,u,v;i<m;++i){cin>>u>>v;g[u].push_back(v);g[v].push_back(u);}
        vector<array<int,2>> d(n+1,array<int,2>{-1,-1});
        queue<pair<int,int>> que;d[1][0]=0;que.push({1,0});
        while(!que.empty()){
            auto [u,p]=que.front();que.pop();
            for(int v:g[u]) if(d[v][p^1]==-1){
                d[v][p^1]=d[u][p]+1;que.push({v,p^1});
            }
        }
        while(q--){
            int a;long long L;cin>>a>>L;
            int dis=d[a][L&1];
            bool ok=!g[1].empty() && dis!=-1 && dis<=L;
            cout<<(ok?"Yes":"No")<<'\n';
        }
        return 0;
    }
    
    • 1

    信息

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