zoukankan      html  css  js  c++  java
  • 最短路计数(spfa)

    题目描述

    给出一个N个顶点M条边的无向无权图,顶点编号为1~N。问从顶点1开始,到其他每个点的最短路有几条。

    输入输出格式

    输入格式:
    输入第一行包含2个正整数N,M,为图的顶点数与边数。

    接下来M行,每行两个正整数x, y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边。

    输出格式:
    输出包括N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出mod 100003后的结果即可。如果无法到达顶点i则输出0。

    输入输出样例

    输入样例#1:
    5 7
    1 2
    1 3
    2 4
    3 4
    2 3
    4 5
    4 5
    输出样例#1:
    1
    1
    1
    2
    4
    说明

    1到5的最短路有4条,分别为2条1-2-4-5和2条1-3-4-5(由于4-5的边有2条)。

    对于20%的数据,N ≤ 100;

    对于60%的数据,N ≤ 1000;

    对于100%的数据,N<=1000000,M<=2000000。

    分析
    spfa+队列优化:
    ans[i]表示有多少条1到i点的最短路。
    双向图,要把2个相连的点正反方向都存储。
    做一个spfa,如果dis[s[i]]+1小于当前的dis[t[i]]就替换,并且ans[t[i]]就等于ans[s[i]]的数量,如果等于把ans[t[i]]跟ans[s[i]]合并。
    最后输出就好了,不过要注意取模。

    程序:

    var
    next,ls,s,t,w,p:array[0..500001]of longint;
    d,a:array[0..1000001]of longint;
    v:array[0..1000001]of boolean;
    n,m,q,i,j,g:longint;
    
    procedure spfa;
    var
    head,tail,i:longint;
    begin
        head:=0;tail:=1;
        d[1]:=0;
        a[1]:=1;
        v[1]:=true;
        p[1]:=1;
        while head<tail do
        begin
            inc(head);
            i:=ls[p[head]];
            while i>0 do
            begin
                if d[s[i]]+1=d[t[i]] then a[t[i]]:=(a[t[i]]+a[s[i]]) mod 100003;
                if d[s[i]]+1<d[t[i]] then
                begin
                    d[t[i]]:=d[s[i]]+1;
                    if v[t[i]]=false then
                    begin
                        v[t[i]]:=true;
                        inc(tail);
                        p[tail]:=t[i];
                    end;
                    a[t[i]]:=a[s[i]];
                end;
                i:=next[i];
            end;
            v[p[head]]:=false;
        end;
    end;
    
    
    begin
        fillchar(next,sizeof(next),0);
        fillchar(ls,sizeof(ls),0);
        readln(n,g);
        i:=0;
        for j:=1 to g do
        begin
            inc(i);
            readln(s[i],t[i]);
            next[i]:=ls[s[i]];
            ls[s[i]]:=i;
            inc(i);
            s[i]:=t[i-1];t[i]:=s[i-1];
            next[i]:=ls[s[i]];
            ls[s[i]]:=i;
        end;
        for i:=1 to n do
        begin
            d[i]:=maxlongint;
            v[i]:=false;
        end;
        spfa;
        for i:=1 to n do
        writeln(a[i]);
    end.
    
    
  • 相关阅读:
    练习
    js简介、基本语法、类型转换、变量、运算符、分支语句、循环语句、函数、函数调用
    样式表、格式布局、流式布局
    表单
    图片热点、网页划区
    JS模拟窗口
    JavaScript 常用功能实现一览(一)
    分页打印控制 摘自于网络:http://www.cnblogs.com/joinger/articles/1807517.html
    我眼中的C#3.0 摘自于网络:http://www.cnblogs.com/joinger/articles/1297237.html
    .net ToString()用法详解与格式说明
  • 原文地址:https://www.cnblogs.com/YYC-0304/p/9500065.html
Copyright © 2011-2022 走看看