CF238E Meeting Her【DP,最短路】
显然,如果节点
那么一个简单的想法是直接把每条边对应的必经点连边跑最短路,当然这样是错的,考虑下面这种情况:
上述做法的问题在于,当我们在坐上
我们不妨把所有
初始值
那个
第二种转移可以直接做,第一种转移我们对
注意转移顺序:由于在第一种转移中可能会把前驱的
预处理
code
/*
最黯淡的一个 梦最为炽热
万千孤单焰火 让这虚构灵魂鲜活
至少在这一刻 热爱不问为何
存在为将心声响彻
*/
#include <bits/stdc++.h>
#define pii pair<int, int>
#define mp(x, y) make_pair(x, y)
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
#define int long long
#define mem(x, v) memset(x, v, sizeof(x))
#define mcpy(x, y) memcpy(x, y, sizeof(y))
#define lob lower_bound
#define upb upper_bound
#define all(x) (x).begin(), (x).end()
#define TIME 1e3 * clock() / CLOCKS_PER_SEC
using namespace std;
inline int read() {
int x = 0, w = 1;char ch = getchar();
while (ch > '9' || ch < '0') { if (ch == '-')w = -1;ch = getchar(); }
while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
return x * w;
}
const int MN = 1e2 + 5;
const int Mod = 998244353;
const int inf = 1e18;
inline int min(int x, int y) { return x < y ? x : y; }
inline int max(int x, int y) { return x > y ? x : y; }
inline int qPow(int a, int b = Mod - 2, int ret = 1) {
while (b) {
if (b & 1) ret = ret * a % Mod;
a = a * a % Mod, b >>= 1;
}
return ret;
}
#define dbg
int N, M, K, a, b, s[MN], t[MN];
int dis[MN][MN], f[MN][MN], g[MN][MN], _dis[MN][MN], d[MN][MN], on[MN][MN], mst[MN][MN];
vector <int> e[MN][MN];
signed main(void) {
N = read(), M = read(), a = read(), b = read();
mem(dis, 0x3f);
for (int i = 1; i <= N; i++) dis[i][i] = 0;
for (int i = 1; i <= M; i++) {
int x = read(), y = read();
dis[x][y] = 1;
}
K = read();
for (int i = 1; i <= K; i++) s[i] = read(), t[i] = read();
mcpy(g, dis);
for (int k = 1; k <= N; k++)
for (int i = 1; i <= N; i++)
for (int j = 1; j <= N; j++)
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
for (int u = 1; u <= N; u++) {
mcpy(_dis, g);
for (int i = 1; i <= N; i++)
_dis[i][u] = _dis[u][i] = inf;
for (int k = 1; k <= N; k++)
for (int i = 1; i <= N; i++)
for (int j = 1; j <= N; j++)
_dis[i][j] = min(_dis[i][j], _dis[i][k] + _dis[k][j]);
for (int i = 1; i <= K; i++)
mst[u][i] = _dis[s[i]][t[i]] != dis[s[i]][t[i]];
}
for (int i = 1; i <= N; i++)
for (int j = 1; j <= K; j++)
on[i][j] = dis[s[j]][t[j]] == dis[s[j]][i] + dis[i][t[j]];
mem(f, 0x3f);
for (int i = 1; i <= K; i++)
if (on[b][i]) f[b][i] = 0;
for (int i = 1; i <= N; i++)
for (int j = 1; j <= K; j++)
for (int k = 1; k <= N; k++)
if (on[i][j] && on[k][j] && dis[i][t[j]] + 1 == dis[k][t[j]] && dis[k][i] == 1) d[k][j]++, e[i][j].pb(k);
for (int i = 0; i < N; i++) {
queue <pii> q;
for (int j = 1; j <= N; j++)
for (int k = 1; k <= K; k++)
if (f[j][k] == i) q.push(mp(j, k));
while (!q.empty()) {
pii x = q.front();
q.pop();
for (int j : e[x.fi][x.se])
if ((!--d[j][x.se]) && f[j][x.se] > i) f[j][x.se] = i, q.push(mp(j, x.se));
}
for (int j = 1; j <= N; j++)
for (int k = 1; k <= K; k++)
if (f[j][k] == i && mst[j][k])
for (int p = 1; p <= K; p++)
f[j][p] = min(f[j][p], f[j][k] + 1);
}
int ans = inf;
for (int i = 1; i <= K; i++) if (mst[a][i]) ans = min(ans, f[a][i]);
printf("%lld\n", ans < inf ? ans + 1 : -1);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】