loj #2316

最短路 + 记忆化
记忆化搜索更容易实现


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>

using namespace std;
const int N = 1e5 + 10, M = 2e5 + 10;
const int oo = (1 << 30);

int head1[N], head2[N], cnt;
struct Node {int v, w, nxt;} G1[M], G2[M];

#define gc getchar()
inline int read() {int x = 0; char c = gc; while(c < '0' || c > '9') c = gc;
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc; return x;}
#undef gc

int n, m, k, Mod;
int dis[N];
bool vis[N];
int f[N][55];
bool c[N][55];

inline void Link(int u, int v, int w) {
	++ cnt;
	G1[cnt].v = v, G1[cnt].w = w, G1[cnt].nxt = head1[u], head1[u] = cnt;
	swap(u, v);
	G2[cnt].v = v, G2[cnt].w = w, G2[cnt].nxt = head2[u], head2[u] = cnt;
}

void Init() {
	cnt = 0;
	for(int i = 1; i <= n; i ++) head1[i] = head2[i] = -1;
	memset(f, -1, sizeof f);
	memset(c, 0, sizeof c);
	for(int i = 1; i <= m; i ++) {
		int u = read(), v = read(), w = read();
		Link(u, v, w);
	}
}

int Q[N << 2];

struct Node_ {
	int u, dis_;
	bool operator < (Node_ a) const {
		return dis_ > a.dis_;
	}
};

priority_queue <Node_> Que;

void Dij() {
	for(int i = 1; i <= n; i ++) vis[i] = 0, dis[i] = oo;
	dis[1] = 0;
	Que.push((Node_) {1, 0});
	while(!Que.empty()) {
		Node_ top_ = Que.top();
		Que.pop();
		if(vis[top_.u]) continue;
		vis[top_.u] = 1;
		int u = top_.u;
		for(int i = head1[u]; ~ i; i = G1[i].nxt) {
			int v = G1[i].v;
			if(dis[v] > dis[u] + G1[i].w) {
				dis[v] = dis[u] + G1[i].w;
				Que.push((Node_) {v, dis[v]});
			}
		}
	}
}

bool flag;

int Dp(int u, int K) {
	if(flag == 0) return 0;
	if(~ f[u][K]) return f[u][K];
	f[u][K] = 0, c[u][K] = 1;
	for(int i = head2[u]; ~ i; i = G2[i].nxt) {
		int v = G2[i].v;
		int t = dis[u] + K - dis[v] - G2[i].w;
		if(t < 0) continue;
		if(c[v][t]) {flag = 0; return 0;}
		(f[u][K] += Dp(v, t)) %= Mod;
	}
	c[u][K] = 0;
	return f[u][K];
}

void Solve() {
	Dij();
	f[1][0] = 1;
	int Ans = 0;
	flag = 1;
	for(int i = 0; i <= k; i ++) {
		(Ans += Dp(n, i)) %= Mod;
		if(flag == 0) {
			cout << "-1" << "\n";
			return ;
		}
	}
	cout << Ans << "\n";
}

int main() {
	for(int T = read(); T; T --) {
		n = read(), m = read(), k = read(), Mod = read();
		Init();
		Solve();
	}
	return 0;
}
posted @ 2018-09-12 15:22  xayata  阅读(133)  评论(0编辑  收藏  举报