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'; } /*不放弃,加油!*/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端