最短路计数

题目描述

给出一个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;
}
posted @ 2017-05-28 17:17  rsqppp  阅读(118)  评论(0)    收藏  举报