和丢人的鸭子与狗不同,鸡是一位伟大的计算机科学家,他正在处理一个经典问题:最小生成树问题。
现在,有 n n n 位选手回答了 m m m个选择题,每个选择题都只能选 L L L 或者 R R R,也就是说,每个选手都会给出一个 m m m 位的 L R LR LR 串。鸡将选手看作了点,两个点之间的边权即为两位选手有多少个回答不同。现在,鸡想要你求出这张图的最小生成树。
思路:
容易想到枚举边权,但这样复杂度上限为 O ( 2 m × n ) O(2^m\times n) O(2m×n)。虽然数据过水导致我过了。。
这时我们想到这样会浪费很多本就不可能到达的边,于是我们一步步扩展可能边。
做法为类似bfs,扩展 a [ i ] a[i] a[i],保存 2 m 2^m 2m 中所有数第一次被访问到的值。
第二次访问就连边。同时可以证明bfs中不同层中上一层的边一定比下一层优。于是我们每跑完一层就执行一遍最小生成树。
时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)
#include<bits/stdc++.h>
#define N 200005
using namespace std;
int read(){
int op=1,sum=0;char ch=getchar();
while(ch<'0'||ch>'9') {
if(ch=='-') op=-1;ch=getchar();}
while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+ch-'0',ch=getchar();
return op*sum;
}
int n,m,a[N];
int fa[N],fr[1<<20],d[1<<20];
inline int get(int x){
return fa[x]^x?fa[x]=get(fa[x]):x;}
queue<int> q;
struct node{
int x,y,w;
}e[1<<22];
bool cmp(node a,node b){
return a.w<b.w;}
int et,res,ans;
inline void solve(){
sort(e+1,e+1+et,cmp);
for(int i=1;i<=et;++i){
int x=e[i].x,y=e[i].y,fx=get(x),fy=get(y);
if(fx^fy){
fa[fx]=fy;ans+=e[i].w;--res;
}
}
et=0;
}
void bfs(){
memset(d,0,sizeof(d));
memset(fr,0,sizeof(fr));
for(int i=1;i<=n;++i)fa[i]=i;
ans=0;res=0;
while(!q.empty())q.pop();
for(int i=1;i<=n;++i)if(!d[a[i]]){
d[a[i]]=1,fr[a[i]]=i,q.push(a[i]);++res;}
// cout<<res<<endl;
int las=0;
while(!q.empty()){
int top=q.front();q.pop();
//cout<<top<<endl;
if(d[top]^las){
//cout<<"L:"<<et<<endl;
solve();las=d[top];
if(res==1){
return ;
}
}
int fx=get(fr[top]),fy;
for(int i=0;i<m;++i){
int to=(top^(1<<i));
//cout<<to<<" "<<top<<" "<<d[to]<<" "<<et<<endl;
if(d[to]){
fy=get(fr[to]);
//cout<<fy<<" "<<fx<<endl;
if(fx^fy){
e[++et].x=fx,e[et].y=fy,e[et].w=d[to]+d[top]-1;}
}else{
d[to]=d[top]+1;fr[to]=fr[top],q.push(to);
}
}
}
solve();
// for(int i=0;i<1<<m;++i)cout<<d[i]<<" ";cout<<endl;
}
char s[25];
int main(){
int T=read();
while(T--){
m=read(),n=read();
for(int i=1;i<=n;++i){
scanf("%s",s);
a[i]=0;
for(int j=0;j<m;++j){
a[i]|=(s[j]=='R')<<j;
}
//cout<<a[i]<<endl;
}
bfs();
printf("%d\n",ans);
}
return 0;
}/*
1
4 5
LRRL
RRRR
RLLL
LLLL
RLRL
*/