PKUACM 2018 D chocolate【并查集+克鲁斯卡尔】

传送:http://poj.openjudge.cn/practice/C18D/
依然是课件截图
1242898-20180719222301777-122095985.png

#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;
}

转载于:https://www.cnblogs.com/lokiii/p/9338798.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值