题解:CF2284E My Mind Is Going
zhang_kevin · · 题解
对于原图
我们对原图的每个连通分量做 dfs,然后将每个连通分量内的节点按照 dfn 排序,再拼接成一个长为
接下来,记
然后类似上述二分,把整个连通块
分析交互次数。第一次二分最多
:::info[参考代码]{open}
提交记录:https://codeforces.com/contest/2284/submission/398086058。
#include<bits/stdc++.h>
#define fo(i, l, r) for(int i = (l); i <= (r); ++i)
using namespace std;
int T, n, m, dfn[2005], tot, p[2005], B[2005], dfnB[2005], totB, q[2005];
vector<int> e[2005];
inline void dfs(int u){
dfn[u] = ++tot;
for(auto v : e[u]){
if(dfn[v]) continue;
dfs(v);
}
return;
}
inline bool cmp(int x, int y){
return dfn[x] < dfn[y];
}
inline void dfs2(int u){
dfnB[u] = ++totB, B[u] = true;
for(auto v : e[u]){
if(dfnB[v]) continue;
dfs2(v);
}
return;
}
inline bool cmp2(int x, int y){
if(!dfnB[x]) return false;
if(!dfnB[y]) return true;
return dfnB[x] < dfnB[y];
}
inline bool cmp3(int x, int y){
if(B[x]) return false;
if(B[y]) return true;
return dfn[x] < dfn[y];
}
signed main(){
cin >> T; while(T--){
cin >> n >> m;
fo(i, 1, m){
int u, v; cin >> u >> v;
e[u].push_back(v), e[v].push_back(u);
}
fo(i, 1, n){
if(!dfn[i]) dfs(i);
p[i] = i;
}
sort(p + 1, p + 1 + n, cmp);
int l = 1, r = n, b2 = p[n];
while(l <= r){
int mid = (l + r) >> 1;
cout << "? 1 " << mid << ' ';
fo(i, 1, mid) cout << p[i] << ' ';
cout << endl;
int res; cin >> res;
if(res == 0){
b2 = p[mid];
r = mid - 1;
}else{
l = mid + 1;
}
}
dfs2(b2); fo(i, 1, n) q[i] = i;
sort(q + 1, q + 1 + n, cmp2);
l = 1, r = totB; int b1 = q[totB];
while(l <= r){
int mid = (l + r) >> 1;
cout << "? 1 " << mid + (n - totB) << ' ';
fo(i, 1, mid) cout << q[i] << ' ';
fo(i, 1, n) if(!B[i]) cout << i << ' ';
cout << endl;
int res; cin >> res;
if(res == 0){
b1 = q[mid];
r = mid - 1;
}else{
l = mid + 1;
}
}
sort(p + 1, p + 1 + n, cmp3);
l = 1, r = n - totB; int a = p[n - totB];
while(l <= r){
int mid = (l + r) >> 1;
cout << "? 1 " << mid + totB << ' ';
fo(i, 1, mid) cout << p[i] << ' ';
fo(i, 1, n) if(B[i]) cout << i << ' ';
cout << endl;
int res; cin >> res;
if(res == 0){
a = p[mid];
r = mid - 1;
}else{
l = mid + 1;
}
}
cout << "? 2 " << a << ' ' << b1 << endl;
int res; cin >> res;
cout << "! " << a << ' ' << (res ? b1 : b2) << '\n';
tot = totB = 0; fo(i, 1, n) dfn[i] = B[i] = dfnB[i] = 0, e[i].clear();
}
return 0;
}
:::