最短路计数
题目描述
给出一个N个顶点M条边的无向无权图,顶点编号为1~N。问从顶点1开始,到其他每个点的最短路有几条。
输入输出格式
输入格式:
输入第一行包含2个正整数N,M,为图的顶点数与边数。
接下来M行,每行两个正整数x, y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边。
输出格式:
输出包括N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出mod 100003后的结果即可。如果无法到达顶点i则输出0。
spfa+记忆化搜索
我发现自己记忆化搜索和动态规划这一块就是屎啊,果然,学了2年。就背了十几个板子。这样有什么意义呢。
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#define FOR(i,u,s) for(int i = head[u];i != s;i = e[i].next)
using namespace std;
void read(int &x)
{
char c = getchar();int flag = 1;x = 0;
while(c<'0'||c>'9'){if(c == '-') flag = -1;c = getchar();}
while('0'<=c&&c<='9')x = x*10+c-'0',c = getchar();
x *= flag;
}
const int maxn = 10003;
const int maxm = 500000;
struct edge{int to,next,v;}e[maxm];
struct Point{int };
int head[maxn],d[maxn],inq[maxn];
int cnt = 0,n,m;
void insert(int u,int v,int w)
{
e[++cnt].to = v;e[cnt].next = head[u];e[cnt].v = w;head[u] = cnt;
e[++cnt].to = u;e[cnt].next = head[v];e[cnt].v = w;head[v] = cnt;
}
const int INF = ~0U>>1;
void spfa(int s)
{
queue<int> Q;
for(int i = 0;i <= n;i++) d[i] = INF;
memset(inq,0,sizeof(inq));
Q.push(s);d[s] = 0;inq[s] = 1;
while(!Q.empty())
{
int u = Q.front();Q.pop();
FOR(i,u,0){
if(d[e[i].to]>d[u]+e[i].v){
d[e[i].to] = d[u] + e[i].v;
if(!inq[e[i].to]){
Q.push(e[i].to);
inq[e[i].to] = 1;
}
}
}
}
}
int f[maxn];
int dfs(int u)
{
if(f[u]) return f[u];
FOR(i,u,0)
if(d[e[i].to] == d[u]-1) f[u] = (f[u]+dfs(e[i].to))%100003;
return f[u];
}
int main()
{
read(n);read(m);
for(int i = 1;i <= m;i++){
int u,v;
read(u),read(v);
insert(u,v,1);
}
spfa(1);
f[1] = 1;
for(int i = 1;i <= n;i++) printf("%d\n",dfs(i));
return 0;
}

浙公网安备 33010602011771号