首先有一个很傻逼的结论:只有叶子节点可能放,证明显然。
所以你把叶子节点全拎出来,二分答案,判断就随一万遍随机顺序放置TPS。然后每次暴力判断就过了。
时间复杂度:$O(Tn^3 \log n)$,但是可以过。

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include<bits/stdc++.h>
using namespace std;
vector<int> v[65];
int n,vis[55],one[105],tot,ch[51],g[51][51];
vector<int> d[65];
bool check2(int mid){
for(int i=1;i<=n;++i)d[i].clear();
for(int i=1;i<=n;++i){
for(int j=1;j<=mid;++j){
d[i].push_back(g[i][ch[j]]);
}
}
for(int i=1;i<=n;++i){
for(int j=i+1;j<=n;++j){
int s=0;
for(int k=1;k<=mid;++k)
s+=d[i][k-1]==d[j][k-1];
if(s==mid)return 0;
}
}
return 1;
}
bool check(int mid){
for(int i=1;i<=10000;++i){
memset(vis,0,sizeof vis);
for(int j=1;j<=mid;++j){
int t=rand()%tot+1;
while(vis[t])t=rand()%tot+1;
ch[j]=one[t];vis[t]=1;
}
if(check2(mid))return 1;
}
return 0;
}
int main(){
srand(10007);
cin>>n;
if(n==1){
cout<<"0\n";return 0;
}
memset(g,0x3f,sizeof g);
for(int i=1;i<=n;++i){
g[i][i]=0;
for(int j=1;j<=n;++j){
char c;cin>>c;
if(c=='Y'){
v[i].push_back(j);
g[i][j]=1;
}
}
}
for(int k=1;k<=n;++k)
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
for(int i=1;i<=n;++i)
if(v[i].size()==1)one[++tot]=i;
int l=1,r=tot;
while(l<r){
int mid=(l+r)>>1;
if(check(mid))r=mid;
else l=mid+1;
}
cout<<l<<'\n';
return 0;
}