1 条题解

  • 0
    @ 2026-5-28 21:50:44

    本蒟蒻第一次写题解 qwq,若有不对请指出。

    分析

    这个题目比较有意思。首先可以注意到,一个点能被加入当且仅当其在一条通向 dd 的最短路上且这条路原先已经覆盖了全部的带花农场。可以用 BFS 算法来处理,在计算最短路的前提下维护最短路的前驱及覆盖的花田数量。如果你这样写,会发现无法通过样例 1。

    分析可得,一个点的最短路可能有多条,而上述方案并不能处理这种情况。于是,改为维护最短路所有前驱以及覆盖最多花田数量。这一部分比较好实现。对于一个节点,其所经过的花田数量就是前驱所经过花田数量的最大值 + 这个节点是否为花田。

    现在,我们需要处理哪些点可以添加。从那些最短路径覆盖花田数量为 KK 开始沿前驱 DFS。如何判断走一个前驱的路径可以覆盖所有花田?我们可以根据经过花田数量的转移方法判断是否是从此方向转移而来,进而判断出那些路可以走。这样子,所经过的点就是可以变成花田的节点。具体可以参照代码理解。

    代码

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <queue>
    using namespace std;
    const int N = 2e5 + 5;
    int hd[N], to[N * 2], nxt[N * 2], num = 1;
    void add(int u, int v) {
        num++;
        to[num] = v;
        nxt[num] = hd[u];
        hd[u] = num;
    }
    int t, n, m, k, l;
    int s[N], d[N];
    int dis[N], fs[N];
    bool vis[N], ok[N];
    bool is[N];
    void dfs(int x) {
        if (ok[x])
            return;
        ok[x] = 1;
        if (x == 1)
            return;
        for (int i = hd[x]; i; i = nxt[i]) {
            int v = to[i];
            if (dis[v] == dis[x] - 1 && fs[v] + is[x] == fs[x])
                dfs(v);
        }
    }
    int main() {
        // freopen("Flowers.in", "r", stdin);
        // freopen("Flowers.out", "w", stdout);
        cin >> t;
        while (t--) {
            cin >> n >> m >> k >> l;
            memset(is, 0, sizeof(is));
            for (int i = 1; i <= k; i++) {
                cin >> s[i];
                is[s[i]] = 1;
            }
            for (int i = 1; i <= l; i++) {
                cin >> d[i];
            }
            memset(hd, 0, sizeof(hd));
            num = 1;
            for (int i = 1; i <= m; i++) {
                int u, v;
                cin >> u >> v;
                add(u, v);
                add(v, u);
            }
            memset(dis, 0x3f, sizeof(dis));
            memset(vis, 0, sizeof(vis));
            memset(fs, 0, sizeof(fs));
            dis[1] = 0;
            queue<int> q;
            q.push(1);
            while (!q.empty()) {
                int u = q.front();
                q.pop();
                for (int i = hd[u]; i; i = nxt[i]) {
                    int v = to[i];
                    if (dis[u] + 1 < dis[v]) {
                        dis[v] = dis[u] + 1;
                        fs[v] = fs[u] + is[v];
                        q.push(v);
                        vis[v] = 1;
                    } else if (dis[u] + 1 == dis[v]) {
                        fs[v] = max(fs[v], fs[u] + is[v]);
                    }
                }
            }
            memset(ok, 0, sizeof(ok));
            // for (int i = 1; i <= n; i++) {
            //     cout << dis[i] << " \n"[i == n];
            // }
            for (int i = 1; i <= l; i++) {
                if (fs[d[i]] == k)
                    dfs(d[i]);
            }
            for (int i = 2; i <= n; i++) {
                if (ok[i])
                    cout << 1;
                else
                    cout << 0;
            }
            cout << endl;
        }
        return 0;
    }
    
    • 1

    信息

    ID
    12479
    时间
    3000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者