CF1514E Baby Ehab's Hyper Apartment
题意
交互题,有一个未知的竞赛图,你有以下两种查询方式:
1 x y,查询 \(x,y\) 间的连边的方向。2 x k y1 y2 y3 ... yk,查询 \(x\) 和 \(y_1,y_2,\cdots,y_k\) 间是否至少存在一条连边。
第一种操作限制为 \(9n\),第二种操作限制为 \(2n\)。
你需要在操作限制内求出任意两点的可达性。
\(n\le 100\)
分析
由于是竞赛图,根据竞赛图基本性质,竞赛图缩点后形成一条链。那么我们只需要求出强连通分量以及链的形态即可。进一步地,我们可以先求出一条哈密顿链(竞赛图基本性质,竞赛图必定存在哈密顿链),然后看看回边的位置就可以容易的求出 SCC 了。
先看看如何求哈密顿链。构造题一种经典方法是增量法,考虑先求出 \([1,i)\) 的哈密顿链,若此时要插入 \(i\),那么在链上肯定存在一个分界点,使得分界点之前的点向 \(i\) 连边,\(i\) 向分界点之后的点连边。我们可以二分找到分界点。需要使用 \(O(n\log n)\le 9n\) 次一操作。
现在考虑求解 SCC。由于是求回边,故考虑倒着考虑,拿出哈密顿链上的末端端点 \(i\),考虑从后往前扫,当前考虑与 \(i\) 同属一个 SCC 的点集为 \(S\),考虑加入 \(j\),使用操作二得到点集内的某一个点 \(k\) 和 \(j\) 及在哈密顿链上在它之前的所有点的边的存在性。若存在,那么 \(j\) 一定和 \(i\) 同属一个 SCC,将 \(j\) 加入 \(S\),然后往前考虑;若不存在,那么 \(k\) 点不再有用,将 \(k\) 从 \(S\) 内“临时”删除(它只是没用了,并不是和 \(i\) 不再在一个 SCC 里了),从点集内换一个点接着考虑,直到点集为空。至此求出了与 \(i\) 位于相同 SCC 的点集,它在哈密顿上为一段后缀,将这段后缀删除,然后对新的末端接着做。由于 \(j,k\) 失配各位导致一次操作二的发生,故操作二总数为 \(2n\)。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<map>
#include<unordered_map>
#include<vector>
#include<queue>
#include<stack>
#include<bitset>
#include<set>
#include<array>
#include<ctime>
#include<random>
#include<cassert>
#define x1 xx1
#define y1 yy1
#define IOS ios::sync_with_stdio(false)
#define ITIE cin.tie(0);
#define OTIE cout.tie(0);
#define PY puts("Yes")
#define PN puts("No")
#define PW puts("-1")
#define P0 puts("0")
#define P__ puts("")
#define PU puts("--------------------")
#define mp make_pair
#define fi first
#define se second
#define gc getchar
#define pc putchar
#define pb emplace_back
#define il inline
#define un using namespace
#define all(x) x.begin(),x.end()
#define mem(x,y) memset(x,y,sizeof x)
#define rep(a,b,c) for(int a=(b);a<=(c);++a)
#define per(a,b,c) for(int a=(b);a>=(c);--a)
#define reprange(a,b,c,d) for(int a=(b);a<=(c);a+=(d))
#define perrange(a,b,c,d) for(int a=(b);a>=(c);a-=(d))
#define graph(i,j,k,l) for(int i=k[j];i;i=l[i].nxt)
#define lowbit(x) ((x)&-(x))
#define lson(x) ((x)<<1)
#define rson(x) ((x)<<1|1)
//#define double long double
//#define int long long
//#define int __int128
using namespace std;
using i64=long long;
using u64=unsigned long long;
using pii=pair<int,int>;
template<typename T1,typename T2>inline void ckmx(T1 &x,T2 y){x=x>y?x:y;}
template<typename T1,typename T2>inline void ckmn(T1 &x,T2 y){x=x<y?x:y;}
inline auto rd(){
int qwqx=0,qwqf=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')qwqf=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){qwqx=(qwqx<<1)+(qwqx<<3)+ch-48;ch=getchar();}return qwqx*qwqf;
}
template<typename T>inline void write(T qwqx,char ch='\n'){
if(qwqx<0){qwqx=-qwqx;putchar('-');}
int qwqy=0;char qwqz[40];
while(qwqx||!qwqy){qwqz[qwqy++]=qwqx%10+48;qwqx/=10;}
while(qwqy--)putchar(qwqz[qwqy]);if(ch)putchar(ch);
}
bool Mbg;
const int maxn=105,inf=0x3f3f3f3f;
const long long llinf=0x3f3f3f3f3f3f3f3f;
int n;
bool G[maxn][maxn],E[maxn][maxn];
void bfs(int s,int t){
if(E[s][t])return;
E[s][t]=1;
rep(i,1,n)if(G[t][i])bfs(s,i);
}
void gen(){
mem(E,0),mem(G,0);
rep(i,1,n)rep(j,1,n)scanf("%1d",&G[i][j]);
rep(i,1,n)bfs(i,i);
}
bool answer1(int x,int y){
return G[x][y];
}
bool answer2(int x,vector<int>v){
bool ok=0;
for(int i:v)ok|=G[x][i];
return ok;
}
bool ask1(int x,int y){
cout<<"1 "<<x-1<<' '<<y-1<<endl;
int _=answer1(x,y);write(_);
// int _=rd();assert(~_);
return _;
}
bool ask2(int x,vector<int>v){
cout<<"2 "<<x-1<<' '<<v.size();
for(int i:v)cout<<' '<<i-1;
cout<<endl;
int _=answer2(x,v);write(_);
// int _=rd();assert(~_);
return _;
}
vector<int>vec;
vector<pii>ans;
bool a[maxn][maxn];
inline void solve_the_problem(){
n=rd(),vec.clear(),ans.clear(),mem(a,0);
gen();
vec.emplace_back(1);
rep(i,2,n){
int l=0,r=(int)vec.size()-1,res=vec.size();
while(l<=r){
int mid=(l+r)>>1;
if(ask1(i,vec[mid]))res=mid,r=mid-1;
else l=mid+1;
}
vec.insert(res+vec.begin(),i);
}
// for(int i:vec)write(i,32);P__;
vector<int>s;
rep(i,0,n-2)s.pb(vec[i]);
for(int i=n-1;i>=0;){
int lst=i,p=i;
while(p>=lst){
while(!s.empty()&&ask2(vec[p],s))lst--,s.pop_back();
--p;
}
ans.pb(mp(lst,i));
if(s.empty())break;
i=lst-1,s.pop_back();
}
rep(i,0,n-2){
rep(j,i+1,n-1){
a[vec[i]][vec[j]]=1;
}
}
rep(i,1,n)a[i][i]=1;
for(pii _:ans){
int l=_.fi,r=_.se;
rep(i,l,r-1)rep(j,i+1,r)a[vec[j]][vec[i]]=1;
}
cout<<3<<endl;
rep(i,1,n){
rep(j,1,n)cout<<a[i][j];
cout<<endl;
}
freopen("log.txt","w",stdout);
bool chk=1;
rep(i,1,n)rep(j,1,n)chk&=(a[i][j]==E[i][j]);
if(chk)printf("ac");
else printf("wa");
return;
int x=rd();
if(x==-1)exit(0);
}
bool Med;
signed main(){
// freopen(".in","r",stdin);freopen(".out","w",stdout);
fprintf(stderr,"%.3lfMB\n",(&Mbg-&Med)/1048576.0);
int _=rd();
while(_--)solve_the_problem();
}
/*
*/

浙公网安备 33010602011771号