其他分享
首页 > 其他分享> > gmoj 6863. 【2020.11.16提高组模拟】食堂计划

gmoj 6863. 【2020.11.16提高组模拟】食堂计划

作者:互联网

\(Solution\)

考虑设\(dis[x]\)表示\(S\)到\(x\)的最短距离,\(ndis[x]\)表示\(x\)到\(T\)的最短距离。

然后设\(f[x][y]\)表示两个人分别在\(x\)和\(y\)处,之后不相交走到\(T\)的方案数。

显然可以记忆化\(dfs\)一波,要保证每个\((x,y)\)都是以最优的路径走到的。

最终答案就是\(f[S][S]/2\)。而如果有\((S,T)\)的边且长度等于最短路的话需要特判一下。

\(Code\)

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 2010
#define mo 1000000009
#define inf 1010580540
#define ll long long
#define mem(x, a) memset(x, a, sizeof x)
#define mpy(x, y) memcpy(x, y, sizeof y)
#define fo(x, a, b) for (int x = (a); x <= (b); x++)
#define fd(x, a, b) for (int x = (a); x >= (b); x--)
#define go(x) for (int p = tail[x], v; p; p = e[p].fr)
#define plus(x, y) x = x + y >= mo ? x + y - mo : x + y
using namespace std;
struct node{int v, fr, w;}e[N << 8];
int n, m, S, T, tail[N], cnt = 0;
int dis[N], ndis[N], dl[N * N << 1];
ll ans = 0, f[N][N];
bool label[N];

inline int read() {
	int x = 0, f = 0; char c = getchar();
	while (c < '0' || c > '9') f = (c == '-') ? 1 : f, c = getchar();
	while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
	return f ? -x : x;
}

inline void add(int u, int v, int w) {e[++cnt] = (node){v, tail[u], w}; tail[u] = cnt;}

void spfa(int x, int *d) {
	int l = 0, r = 1; dl[1] = x;
	fill(d + 1, d + n + 1, inf);
	d[x] = 0;
	while (l++ < r) {
		int x = dl[l];
		go(x) {
			v = e[p].v;
			if (d[v] > d[x] + e[p].w) {
				d[v] = d[x] + e[p].w;
				if (! label[v]) label[v] = 1, dl[++r] = v;
			}
		}
		label[x] = 0;
	}
}

int dfs(int x, int y) {
	if (x == T && y == T) return 1;
	if (x != S && x == y) return 0;
	if (f[x][y] != -1) return f[x][y];
	int res = 0, t = 0;
	go(x) {
		v = e[p].v;
		if (dis[v] < dis[x] + e[p].w) continue;
		if (dis[v] + ndis[v] > dis[T]) continue;
		if (dis[v] > dis[y]) t = dfs(y, v);
		else t = dfs(v, y); plus(res, t);
	}
	return f[x][y] = res;
}

ll ksm(ll x, int y) {
	ll s = 1;
	while (y) {
		if (y & 1) s = s * x % mo;
		x = x * x % mo, y >>= 1;
	}
	return s;
}

int main()
{
	freopen("dining.in", "r", stdin);
	freopen("dining.out", "w", stdout);
	n = read(), m = read(), S = read(), T = read();
	fo(i, 1, m) {
		int u = read(), v = read(), w = read();
		if (! f[u][v] || w < f[u][v]) f[u][v] = w;
	}
	
	fo(i, 1, n) fo(j, 1, n)
		if (f[i][j]) add(j, i, f[i][j]);
	spfa(T, ndis);
	
	fill(tail + 1, tail + n + 1, 0), cnt = 0;
	int can = 0;
	fo(i, 1, n) fo(j, 1, n)
		if (f[i][j]) {
			if (i == S && j == T && f[i][j] == ndis[S]) can = 1;
			add(i, j, f[i][j]);
		}
	spfa(S, dis);
	
	mem(f, -1);
	dfs(S, S);
	if (can) f[S][S]++;
	printf("%lld\n", 1LL * f[S][S] * ksm(2, mo - 2) % mo);
	return 0;
}

标签:return,16,int,mo,dis,read,2020.11,gmoj,define
来源: https://www.cnblogs.com/jz929/p/13991489.html