【SPFA】 最短路计数
最短路计数
【问题描述】
给出一个N个顶点M条边的无向无权图,顶点编号为1~N。问从顶点1开始,到其他每个点的最短路有几条。
【输入格式】
输入第一行包含2个正整数N,M,为图的顶点数与边数。
接下来M行,每行两个正整数x, y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边。
【输出格式】
输出包括N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出mod 100003后的结果即可。如果无法到达顶点i则输出0。
【输入样例】
5 7 1 2 1 3 2 4 3 4 2 3 4 5 4 5
【输出样例】
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 ≤ 100000,M ≤ 200000。
【试题分析】
非常显然,因为上午学了SPFA,准备找一题练练手……
邻接表秒过,主要老是有个BUG
还好吃了顿饭就醒悟了……
SPFA一遍就行了。
【代码】
#include<iostream> #include<cstring> #include<cstdio> using namespace std; int cnt=0; int Root[400002],Node[400002],Next[400002]; int que[400002],dis[400002]; bool vis[400002]; int ans[400002]; int N,M; void add(int u,int v,int w){//邻接表存储 cnt++; Node[cnt]=v; Next[cnt]=Root[u]; Root[u]=cnt; } void SPFA(int s){ memset(vis,false,sizeof(vis)); for (int i=1; i<=N; i++) dis[i]=9999999; memset(que,0,sizeof(que)); int tail=1; que[tail]=s; dis[s]=0; ans[1]=1; vis[s]=true; for(int head=1;head<=tail;head++){ for(int x=Root[que[head]];x!=0;x=Next[x]){ if(dis[que[head]]+1<dis[Node[x]]){ dis[Node[x]]=dis[que[head]]+1; ans[Node[x]]=ans[que[head]]%100003; if(vis[Node[x]]==false){ que[++tail]=Node[x]; vis[Node[x]]=true; } } else if(dis[que[head]]+1==dis[Node[x]]) ans[Node[x]]=(ans[Node[x]]+ans[que[head]])%100003;//等于就更新答案 } vis[Node[head]]=false; } } int main(){ cin>>N>>M; for(int i=0;i<M;i++){ int u,v,w=1; scanf("%d%d",&u,&v); add(u,v,w);//由于我们要存的是双向图,所以注意要储存两次 add(v,u,w);//注意数组开两倍 } SPFA(1); for(int i=1;i<=N;i++) cout<<ans[i]<<endl;//输出 }
你——悟到了么?