假设我们按照某一种随机的规则在两个同源变形虫中取一个数,那么由于有l/2是相同的,因此概率为1/4。如果我们给每一个基因定一个值,然后定义一个变形虫的值就是它l个基因中的最小值,那么两个同源变形虫相同的概率就是1/3;两个不同源为1/l。如果取两个,就分别是1/9和1/l^2=1/n。
那么每次给每个基因随机定值,这样一次可以得到n/9对,不断操作即可。
AC代码如下:
#include<bits/stdc++.h>
#define N 35005
#define M 4000005
using namespace std;
int n,m,l,tot,pt,cnt,q1[M],q2[M],a[N][135],mrk[M],mch[N];
struct node{ int x,y,z; }b[N];
struct hsh{
int fst[2010527],pnt[M],nxt[M];
int ins(int x){
int y=x%2010527,p;
for (p=fst[y]; p; p=nxt[p])
if (pnt[p]==x) return p;
pnt[++tot]=x; nxt[tot]=fst[y]; fst[y]=tot;
return tot;
}
}h;
bool cmp(const node &u,const node &v){
return u.x<v.x || u.x==v.x && u.y<v.y;
}
bool eql(int x,int y){
pt++; int i,sum=0;
for (i=1; i<=l; i++) mrk[a[x][i]]=pt;
for (i=1; i<=l; i++)
if (mrk[a[y][i]]==pt) sum++;
return sum==(l>>1);
}
int solve(){
int i,j,u,v; cnt=0;
random_shuffle(q1+1,q1+tot+1); random_shuffle(q2+1,q2+tot+1);
for (i=1; i<=n; i++) if (!mch[i]){
b[++cnt].x=q1[a[i][1]];
b[cnt].y=q2[a[i][1]];
for (j=2; j<=l; j++){
b[cnt].x=min(b[cnt].x,q1[a[i][j]]);
b[cnt].y=min(b[cnt].y,q2[a[i][j]]);
}
b[cnt].z=i;
}
sort(b+1,b+cnt+1,cmp);
int ans=0;
for (i=1; i<=cnt; i=j+1){
for (j=i; j<cnt && b[j+1].x==b[j].x && b[j+1].y==b[j].y; j++);
for (u=i; u<j; u++) if (!mch[b[u].z])
for (v=u+1; v<=j; v++) if (!mch[b[v].z])
if (eql(b[u].z,b[v].z)){
mch[b[u].z]=b[v].z;
mch[b[v].z]=b[u].z;
ans++; break;
}
}
return ans;
}
int main(){
srand(20160513);
scanf("%d%d%d",&n,&m,&l); n<<=1; int i,j,k,x;
char ch=getchar(); while (ch<'!') ch=getchar();
for (i=1; i<=n; i++)
for (j=1; j<=l; j++){
x=0;
for (k=0; k<4; k++,ch=getchar())
x=(x<<7)+(int)ch;
a[i][j]=h.ins(x);
}
for (i=1; i<=tot; i++) q1[i]=q2[i]=i;
x=n>>1;
while (x) x-=solve();
for (i=1; i<=n; i++) printf("%d\n",mch[i]);
return 0;
}
by lych
2016.5.13