#include<bits/stdc++.h> #define debug(x) cout << #x << ":\t" << (x) << endl; usingnamespace std; #define ll long long #define ull unsigned ll constint N = 2e6 + 5; constint INF = 0x3f3f3f3f; const ll inf = 0x3f3f3f3f3f3f3f3f; const ll mod = 1e9 + 7; const ll inv2 = (mod + 1) / 2; int T; int n, m; int par[N]; voidinit(int n){ for (int i = 0; i <= n; i++)par[i] = i; } intfind(int i){ return par[i] == i ? i : par[i] = find(par[i]); } voidunit(int x, int y){ par[find(x)] = find(y); } vector<int>G[N], g[N]; boolck(){ for (int i = 2; i <= n; i++)if (find(i) != find(1))returnfalse; returntrue; } int vis[N]; vector<int>vc; voiddfs(int u, int _fa){ if (!vis[u]) { vc.push_back(u); for (int v : g[u])vis[v] = 1; } for (int v : G[u]) { if (v != _fa)dfs(v, u); } } intmain(){ scanf("%d", &T); while (T--) { scanf("%d%d", &n, &m); init(n); for (int i = 1; i <= n; i++)G[i].clear(), vis[i] = 0, g[i].clear(); for (int i = 1; i <= m; i++) { int u, v; scanf("%d%d", &u, &v); g[u].push_back(v); g[v].push_back(u); if (find(u) != find(v)) { unit(u, v); G[u].push_back(v); G[v].push_back(u); } } if (!ck()) { puts("NO"); continue; } vc.clear(); dfs(1, 0); puts("YES"); printf("%d\n", (int)vc.size()); for (int u : vc)printf("%d ", u); puts(""); } return0; }
C. Strange Shuffle
题意:交互题。有 n 个人排成环形,初始每人有 k 点,每轮每个人给左边的人 ⌊2ai⌋,给右边的人 ⌈2ai⌉,ai 为这个人现在有的点数。这 n 个人中有一个内鬼,他会给左边的人 0,给右边的人 ai。要求用不超过 1000 次询问,每次问一个人当前的点数,每次询问后即过一轮,要找出内鬼。
思维
打表发现,内鬼始终等于 k,内鬼左侧第 i 轮有 i 个人小于 k,右侧第 i 轮有 i 个人大于 k。
从任意一点开始,第 i 轮向右跳 i 个人,询问,若 大于或小于 k,则再向左或向右逐个询问,直到找到等于 k 的位置就是内鬼。
每次跳 i 个人保证了在 n 步内一定能找到大于或小于 k 的位置,再由于每轮大于或小于 k 的人数只加 1,所以在 n 步内一定能找到内鬼。