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