ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

洛谷P1144 最短路计数 及其引申思考

2021-05-20 22:53:21  阅读:218  来源: 互联网

标签:输出 洛谷 短路 spfa P1144 顶点 重边 define


图论题目练得比较少,发一道spfa的板子题目~

题目:P1144

题目描述

给出一个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。


 

Solution:

一眼数据范围,吓得就是一滚~,关键是还有重边,而且spfa只能记录单点到其它点的一条最短路,这题又要输出最短路个数取模,让人琢磨不透。So,默默的看看标签吧,普及+提高,嗯貌似不是很难,看下解题标签:spfa,bfs,图论,最短路。OK,果然还是要用到spfa,我们关键是要想到如何去处理重边和最短路计数。于是乎,我们先写一下spfa的模板,然后再来思考,不难发现:边权都为1,对于重边在spfa中会进行多次才到下一个点,所以路径数会记录下来,而且在spfa的松弛操作中由于边权均为1所以每个点只会松弛一次,于是乎在跑spfa时我们只需判断dis[v]==dis[u]+1是否成立,若成立,对于ans就加上到u点的边的条数再取模。这样这道题就完美的解决了。

代码:

 1 #include<bits/stdc++.h>
 2 #pragma GCC optimize(2)
 3 using namespace std;
 4 #define ll long long
 5 #define il inline
 6 #define mod 100003
 7 #define N 1000005
 8 #define inf 233333333
 9 int n,m,h[N],dis[N],cnt,ans[N];
10 bool vis[N];
11 queue<int>q;
12 il int gi()
13 {
14     int a=0;char x=getchar();bool f=0;
15     while((x<'0'||x>'9')&&x!='-')x=getchar();
16     if(x=='-')x=getchar(),f=1;
17     while(x>='0'&&x<='9')a=a*10+x-48,x=getchar();
18     return f?-a:a;
19 }
20 struct edge{
21 int to,net;
22 }e[N<<2];
23 il void add(int u,int v){e[++cnt].to=v;e[cnt].net=h[u];h[u]=cnt;}
24 il void spfa(int s)
25 {
26     for(int i=1;i<=n;i++)dis[i]=inf;
27     q.push(s);
28     vis[s]=1;ans[s]=1;dis[s]=0;
29     int u,v;
30     while(!q.empty())
31     {
32         u=q.front();
33         q.pop();vis[u]=0;
34         for(int i=h[u];i;i=e[i].net){
35             v=e[i].to;
36             if(dis[u]+1<dis[v]){
37                 dis[v]=dis[u]+1;
38                 ans[v]=ans[u];
39                 if(!vis[v])vis[v]=1,q.push(v);
40             }
41             else if(dis[v]==dis[u]+1)ans[v]=(ans[v]+ans[u])%mod;
42         }
43     }
44 }
45 int main()
46 {
47     n=gi(),m=gi();
48     int u,v;
49     for(int i=1;i<=m;i++)
50     {
51         u=gi(),v=gi();
52         add(u,v);add(v,u);
53     }
54     spfa(1);
55     for(int i=1;i<=n;i++)printf("%d\n",ans[i]);
56     return 0;
57 }

 

思考:

由这道题我们想到,如果对与任意一个有向无环且带权的图,需要输出规定原点到其它点的最短路径条数,这样应该怎么去做呢?

我们可以先跑一遍spfa,再进行DAG+DP(或者记忆化搜索),也可以直接两遍spfa跑过(YZK大佬告诉我的方法,仔细想想思路都差不多,原理还是DP),于是乎,论DP的重要性,当然也可以看出spfa的应用有多广泛。。。

推广题:POJ3463(解题报告)

标签:输出,洛谷,短路,spfa,P1144,顶点,重边,define
来源: https://blog.51cto.com/u_15180869/2799041

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有