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。
spfa
spfa用了优化了,其实没必要,普通的队列就行。
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
#include<deque>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=2000010;
struct node{
int from,to,next;
}s[maxn];
int head[maxn],num,cnt[maxn],dis[maxn],vis[maxn];
void add(int u,int v){
s[++num].next=head[u];
s[num].from=u;
s[num].to=v;
head[u]=num;
}
void spfa(int x){
memset(dis,inf,sizeof(dis));
// priority_queue<int,vector<int>,greater<int> >q;
deque<int>q;
dis[x]=0;
cnt[x]=vis[x]=1;
q.push_back(x);
while(!q.empty()){
int t=q.front();
q.pop_front();
vis[t]=0;
for(int i=head[t];i;i=s[i].next){
int to=s[i].to;
if(dis[s[i].to]>dis[s[i].from]+1){
dis[s[i].to]=dis[s[i].from]+1;
if(!vis[s[i].to]){
vis[s[i].to]=1;
if(!q.empty()&&dis[to]<dis[q.front()])
q.push_front(to);
else q.push_back(to);
}
cnt[s[i].to]=cnt[s[i].from];//覆盖
}
else if(dis[s[i].to]==dis[s[i].from]+1){
cnt[s[i].to]+=cnt[s[i].from];//继承
if(cnt[s[i].to]>=100003)
cnt[s[i].to]-=100003;
//q.push_back(s[i].to);
}
}
}
}
int main()
{
int m,i,j,n,x,y,k,ans=inf;
scanf("%d %d",&n,&m);
while(m--){
scanf("%d %d",&x,&y);
add(x,y);
add(y,x);
}
spfa(1);
for(i=1;i<=n;i++)
if(cnt[i]==inf) printf("0\n");
else printf("%d\n",cnt[i]);
return 0;
}
另一种解法:
因为所有的边权都为1,所以一个点的最短路就相当于是它在BFS搜索树中的深度。
一个点最短路一定经过了一个层数比它少一的结点(否则不是最短路)。
所以用每个相邻且层数比当前结点层数少一的点更新当前点的路径跳数即可。
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=2000010;
struct node{
int from,to,next;
}s[maxn];
int head[maxn],num,cnt[maxn],dis[maxn],vis[maxn],dep[maxn];
void add(int u,int v){
s[++num].next=head[u];
s[num].from=u;
s[num].to=v;
head[u]=num;
}
void spfa(int x){
memset(dis,inf,sizeof(dis));
queue<int>q;
dis[x]=0;
cnt[x]=vis[x]=1;
dep[x]=0;
q.push(x);
while(!q.empty()){
int t=q.front();
q.pop();
for(int i=head[t];i;i=s[i].next){
int u=s[i].to;
if(!vis[u]){
vis[u]=1;
dep[u]=dep[t]+1;
q.push(u);
}
if(dep[u]==dep[t]+1){
cnt[u]=(cnt[u]+cnt[t])%100003;
}
}
}
}
int main()
{
int m,i,j,n,x,y;
scanf("%d %d",&n,&m);
while(m--){
scanf("%d %d",&x,&y);
add(x,y);
add(y,x);
}
spfa(1);
for(i=1;i<=n;i++)
printf("%d\n",cnt[i]);
return 0;
}