洛谷P1144 最短路计数

展开
题目描述
给出一个NN个顶点MM条边的无向无权图,顶点编号为1-N1−N。问从顶点11开始,到其他每个点的最短路有几条。

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

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

输出格式
共NN行,每行一个非负整数,第ii行输出从顶点11到顶点ii有多少条不同的最短路,由于答案有可能会很大,你只需要输出ans \bmod 100003ansmod100003后的结果即可。如果无法到达顶点ii则输出00。

输入输出样例
输入 #1复制
5 7
1 2
1 3
2 4
3 4
2 3
4 5
4 5
输出 #1复制
1
1
1
2
4
说明/提示
11到55的最短路有44条,分别为22条1-2-4-51−2−4−5和22条1-3-4-51−3−4−5(由于4-54−5的边有22条)。

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

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

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

思路: bfs的vis标记打在外面,意味着每个点只能使用一次。打在里面,意味着每个点只能被使用一次。dfs的vis则打在外面打在里面关系不大,反正打了标记的点都不能跑。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

const int maxn = 2e6;
const int mod = 100003;
vector<int>G[maxn];
int d[maxn],f[maxn],v[maxn];

void bfs()
{
    queue<int>q;
    q.push(1);
    d[1] = 0;
    f[1] = 1;
    v[1] = 1;
    while(!q.empty())
    {
        int now = q.front();q.pop();
        for(int i = 0;i < G[now].size();i++)
        {
            int to = G[now][i];
            if(!v[to])
            {
                d[to] = d[now] + 1;
                f[to] = f[now] % mod;
                v[to] = 1;
                q.push(to);
            }
            else
            {
                if(d[to] == d[now] + 1)
                    f[to] = (f[to] + f[now]) % mod;
            }
        }
    }
}

int main()
{
    int n,m;scanf("%d%d",&n,&m);
    for(int i = 1;i <= m;i++)
    {
        int x,y;scanf("%d%d",&x,&y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
    bfs();
    for(int i = 1;i <= n;i++)
    {
        printf("%d\n",f[i] % mod);
    }
    return 0;
}

你可能感兴趣的:(#,洛谷,#,最短路)