ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2020-11-16 22:00:41  阅读:267  来源: 互联网

标签:return 16 int mo dis read 2020.11 gmoj define


\(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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有