随笔 - 18  文章 - 0  评论 - 2  阅读 - 411

Mock 3: CEOI2021 Day1 P3

让我简化一下题目吧:

有两个玩家, A和B。A并不知道B的位置,但是B知道A的位置然后可以做相应的动作。

让B在任何结点, 做一个路径保证A肯定会抓到B或表示抓不到B。路径必须最短.

每个回合B必须要往一个相邻的结点移动,不能停在原地。

 

我是先考虑链的情况:

非常明显的是肯定可以抓到。 那么路径怎么做?

考虑n=5, 1-2-3-4-5

那么我们走1,2,3,4,5走完就对了?错的 (雾)

我们必须走两次来回,因为我们考虑把图涂成黑白色. 我们走一次只能排除其中一个颜色罢了。

 

所以是1->2->3->4->5->5->4->3->2->1?

哦哦哦哦哦,我明白了-> submit (0分)

????

 

看会题目发现B每个回合必须动, 那么两边不需要考虑. 那么就是 2->3->4->4->3->2 咯

哦哦哦哦哦,我明白了-> submit (8分)怎么那么少(;´д`)ゞ

 

hmmm。突然想起来就是肯定不能有环(cycle)。 想象一下以前玩捉迷藏,秦王绕柱的样子.

那么如果我加一个结点在链上呢?那么不就和星星差不多嘛?不用考虑

那么如果我加两个结点在链上呢?哦,那么我们画个图吧。  以下为样例图:

1-2-3-4-5-6-7-8-9

     10

        11

那么我们就需要去到下面一个节点 2->3->4->5->10->5->6->7->8->8->7->6->5->10->5->4->3->2

那么如果我加三个结点在链上呢?应该也可以吧?(不可以)

1-2-3-4-5-6-7-8-9

     10

        11

        12

考虑一下我们从左走到右那么我们呢就需要下去到 11 但是呢我们走了5->10->11->10->5 若B在6,B可以偷偷的去4,但是我们继续走到6->7->8....

那样的话,我们就需要找到最长的链把其他的结点当成刚刚讨论的加结点。那么我们跑两次dfs就可以了。

具体代码:

复制代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1500;
vector<int>g[N], e[N];
int d[N], fa[N], vis[N], n, m;
void reject() {
    cout << "NO\n"; exit(0);
}
void special() {
    if (m >= n) {
        reject();
    }
    if (n == 1) { cout << "YES\n1\n1"; exit(0); }
    if (n == 2) { cout << "YES\n2\n1 1"; exit(0); }
}
signed main() {
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin >> n >> m;
    special();
    for (int i = 0; i < m; i++) {
        int u, v; cin >> u >> v;
        g[u].push_back(v); g[v].push_back(u);
    }
    function<void(int, int)> dfs = [&](int u, int f) {
        d[u] = d[f] + 1; fa[u] = f;
        for (auto& v : g[u]) {
            if (v == f) continue;
            dfs(v, u);
        }
    };
    function<void(int, int)> dfs2 = [&](int u, int f) {
        for (auto& v : g[u]) {
            if (v == f) continue;
            dfs2(v, u); d[u] = max(d[u], d[v]);
        }
    };
    dfs(1, 0);
    int mx = 1; for (int i = 1; i <= n; i++) if (d[i] > d[mx]) mx = i;
    dfs(mx, 0); int mx2 = 1; for (int i = 1; i <= n; i++) if (d[i] > d[mx2]) mx2 = i;
    int tmp = mx2; vector<int> c;
    while (tmp) {
        c.push_back(tmp);
        vis[tmp] = 1;
        tmp = fa[tmp];
    }
    for (int i = 1; i <= n; i++) {
        if (!vis[i] && vis[fa[i]]) {
            dfs2(i, fa[i]);
            if (d[i] >= d[fa[i]] + 3) {
                reject();
            }
            if (d[i] == d[fa[i]] + 2) e[fa[i]].push_back(i);
        }
    }
    int sz = c.size(); vector<int> ans;
    for (int i = 1; i < sz - 1; i++) {
        ans.push_back(c[i]);
        for (auto& v : e[c[i]])ans.push_back(v), ans.push_back(c[i]);
    }
    for (int i = sz - 2; i >= 1; i--) {
        ans.push_back(c[i]);
        for (auto& v : e[c[i]])ans.push_back(v), ans.push_back(c[i]);
    }
    cout << "YES\n";
    cout << ans.size() << '\n';
    for (int i = 0; i < ans.size(); i++) {
        cout << ans[i] << ' ';
    }
    cout << '\n';
}
/*不放弃,加油!*/
复制代码

 

posted on   yl_neo  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示