1 条题解

  • 0
    @ 2024-5-12 8:29:24

    思路

    单源最短路,本题可以使用bfs来解决,只需要将板子稍加修改即可。

    我们设 paipa_i 为点 11ii 的最短路长度,初始 pai={0,i=1,i>1pa_i=\begin{cases}0,\,i=1\\\infty,\,i>1\end{cases}

    cnticnt_i 为最短路条数,初始 cnti={1,i=10,i>1cnt_i=\begin{cases}1,\,i=1\\0,\,i>1\end{cases}

    如果当前遍历到的节点为 ii,它的上一个节点为 xx,那么:

    • 如果 pai>pax+1pa_i>pa_x+1,说明点 ii 之前没有被遍历过,那么我们令 pai=pax+1pa_i=pa_x+1cnti=cntxcnt_i=cnt_x
    • 如果 pai=pax+1pa_i=pa_x+1,说明最短路长度相同(存在环),那么我们令 cnti=cnti+cntxcnt_i=cnt_i+cnt_x,加上取模就是 cnti=(cnti+cntx)mod100003cnt_i=(cnt_i+cnt_x)\mod 100003

    这其实也是应用了动态规划的思想。

    AC Code

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const ll N=1e6+5,MOD=100003;
    ll n,m,pa[N],cnt[N];
    vector<ll> vec[N];
    queue<ll> q;
    int main(){
        scanf("%lld%lld",&n,&m);
        for(ll i=1,u,v;i<=m;i++)
            scanf("%lld%lld",&u,&v),vec[u].push_back(v),vec[v].push_back(u);
        // 初始化数组
        memset(pa,0x3f,sizeof(pa));
        pa[1]=0,cnt[1]=1; 
        q.push(1); // 将初始点加入队列
        while(!q.empty()){
            ll x=q.front();
            q.pop();
            for(auto i=vec[x].begin();i!=vec[x].end();i++)
                // 按照上述思路判断
                if(pa[*i]>pa[x]+1){
                    pa[*i]=pa[x]+1;
                    cnt[*i]=cnt[x];
                    q.push(*i);
                }else if(pa[*i]==pa[x]+1)
                    cnt[*i]=(cnt[*i]+cnt[x])%MOD;
        }
        for(ll i=1;i<=n;i++)
            printf("%lld\n",cnt[i]);
        return 0;
    }
    
    
    • 1

    信息

    ID
    735
    时间
    1000ms
    内存
    512MiB
    难度
    4
    标签
    递交数
    100
    已通过
    47
    上传者