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
",ans);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/lokiii/p/9338798.html