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;
}
posted @ 2024-04-18 09:02  xiaruize  阅读(12)  评论(0)    收藏  举报