PKUACM 2018 D chocolate【并查集+克鲁斯卡尔】
传送:http://poj.openjudge.cn/practice/C18D/
依然是课件截图
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int N=405,mod=1e9+7,inf=2e9;
int T,n,d[N][N],f[N];
long long a[N];
char s[N][N];
struct qwe
{
int u,v,w;
}e[N*N];
bool cmp(const qwe &a,const qwe &b)
{
return a.w<b.w;
}
int dis(char a[],char b[])
{
int la=strlen(a+1)+1,lb=strlen(b+1)+1;
for(int i=1;i<=la;i++)
d[i][1]=i;
for(int i=1;i<=lb;i++)
d[1][i]=i;
for(int i=2;i<=la;i++)
for(int j=2;j<=lb;j++)
{
if(a[i-1]==b[j-1])
d[i][j]=d[i-1][j-1];
else
d[i][j]=min(d[i][j-1],d[i-1][j])+1;
}
return d[la][lb];
}
int zhao(int x)
{
return x==f[x]?x:f[x]=zhao(f[x]);
}
int hb(int x,int y)
{
x=zhao(x),y=zhao(y);
if(x==y)
return x;
f[x]=y;
return y;
}
bool ok(int x,int cnt)
{
int mn=inf,mx=-inf;
for(int i=1;i<=cnt;i++)
{
int fu=zhao(e[i].u),fv=zhao(e[i].v);
if(fu==x&fv==x)
mx=max(mx,e[i].w);
else if((fu==x&&fv!=x)||(fu!=x&&fv==x))
mn=min(mn,e[i].w);
}
return mx<mn;
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
f[i]=i,a[i]=1;
for(int i=1;i<=n;i++)
scanf("%s",s[i]+1);
int cnt=0;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
e[++cnt]=(qwe){i,j,dis(s[i],s[j])};
sort(e+1,e+1+cnt,cmp);
long long ans=0;
int tot=n;
for(int i=1;i<=cnt;i++)
{
int fu=zhao(e[i].u),fv=zhao(e[i].v);
if(fu==fv)
continue;
int nw=hb(e[i].u,e[i].v);
a[nw]=a[fu]*a[fv]%mod;
if(ok(nw,cnt))
a[nw]=(a[nw]+1)%mod;
tot--;
if(tot==1)
ans=a[nw];
}
printf("%lld\n",ans);
}
return 0;
}