POI2009BAJ-The_Walk_of_Bytie-boy
POI #Year2009 #dp #bfs
\(dp_{i,j}\) 表示 \(i \rightarrow j\) 的最小距离,考虑暴力的转移需要枚举两个,是 \(\mathcal{O}(m^2)\) 的
考虑将这个转移拆成 \(2\) 步,每次先枚举 \(j\) 处添加一个,再在 \(i\) 处添加一个
即令 \(f_{i,j,c}\) 表示 \(i\rightarrow j\) 最后多一个 \(c\) 字符的最短路径
\(bfs\) 转移,记录前驱,然后搞方案即可
// Author: xiaruize
const int N = 4e2 + 10;
int n, m;
vector<pii> g[N], rev[N];
int dp[N][N], f[N][N][27];
tuple<int, int, int> pre[N][N][27];
void bfs()
{
queue<tuple<int, int, int>> q;
mms(dp, 0x3f);
mms(f, 0x3f);
rep(i, 1, n)
{
dp[i][i] = 0;
q.push({i, i, 0});
rep(j, 1, 26)
{
f[i][i][j] = 0;
q.push({i, i, j});
}
}
while (!q.empty())
{
auto [u, v, w] = q.front();
q.pop();
if (!w)
{
for (auto [vv, ww] : g[v])
{
if (f[u][vv][ww] > dp[u][v] + 1)
{
f[u][vv][ww] = dp[u][v] + 1;
pre[u][vv][ww] = {u, v, w};
q.push({u, vv, ww});
}
}
}
else
{
for (auto [uu, ww] : rev[u])
{
if (w != ww)
continue;
if (dp[uu][v] > f[u][v][w] + 1)
{
dp[uu][v] = f[u][v][w] + 1;
pre[uu][v][0] = {u, v, w};
q.push({uu, v, 0});
}
}
}
}
}
void solve()
{
cin >> n >> m;
rep(i, 1, m)
{
char c;
int u, v, w;
cin >> u >> v >> c;
w = c - 'a' + 1;
debug(u, v, w);
g[u].push_back({v, w});
rev[v].push_back({u, w});
}
bfs();
int d;
cin >> d;
int la;
cin >> la;
rep(i, 1, d - 1)
{
int x;
cin >> x;
if (dp[la][x] > 1e9)
cout << "-1" << endl;
else
{
cout << dp[la][x] << ' ';
int u = la, v = x, w = 0;
vector<int> res;
res.resize(dp[la][x] + 1);
int l = 1, r = dp[la][x];
while (get<0>(pre[u][v][w]))
{
auto [uu, vv, ww] = pre[u][v][w];
if (!w)
res[l++] = ww;
else
res[r--] = w;
u = uu;
v = vv;
w = ww;
}
debug(res);
rep(i, 1, dp[la][x]) cout << (char)(res[i] + 'a' - 1);
cout << endl;
}
la = x;
}
}
#ifndef ONLINE_JUDGE
bool end_of_memory_use;
#endif
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int testcase = 1;
// cin >> testcase;
while (testcase--)
solve();
#ifndef ONLINE_JUDGE
cerr << "Memory use:" << (&end_of_memory_use - &start_of_memory_use) / 1024.0 / 1024.0 << "MiB" << endl;
cerr << "Time use:" << (double)clock() / CLOCKS_PER_SEC * 1000.0 << "ms" << endl;
#endif
return 0;
}