PKUACM 2018 D Chocolate 最小生成樹 Kruskal 最長公共子序列
$ \rightarrow $ 戳我進POJ原題
D:Chocolate
總時間限制: 1000ms $ \quad $ 內存限制: 65536kB
描述
Vincent is a chocolate enthusiast and a collector of chocolate since he was young.
He has $ N $ chocolates in total.
For simplicity, each chocolate can be denoted by a string (only contains characters "a" - "z").
with insertion and deletion as the only two edit operations, both at unit cost.
For instance, The edit distance between "kitten" and "sitting" is $ 5 $ :
- delete k at $ 0 $
- insert s at $ 0 $
- delete e at $ 4 $
- insert i at $ 4 $
- insert g at $ 6 $
for a total cost/distance of $ 5 $ operations.
Vincent wants to divide his chocolates into some group(s) (specially, one group is also acceptable),
a plan is acceptable if and only if:
The difference between any two chocolates at the same group must be less
than the difference from any chocolate at this group to any chocolate at any other group.
Can you help Vincent figure out how many different plans are acceptable?
輸入
The first line contains an integer $ T (1 \le T \le 30 ) $ , indicating the number of test cases.
For each test case:
The first line contains one integer $ N ( 2\le N \le 400) $ , indicating the number of chocolates.
Next $ N $ lines, each line contains one string $ S_i $ , each string only contains characters "a" - "z",
and its length won‘t be larger than $ 20 $ . The total length of strings won‘t be larger than $ 10,000 $ .
輸出
For each test case, output your answer in a single line.
An answer should contain one number, indicating the number of different plans.
Since the number can be extremely large, please output the answer modulo $ (10^9 + 7) $ .
樣例輸入
4
3
godivachocolate
roycechocolate
richartchocolate
3
chocolate
milkchocolate
darkchocolate
4
ab
bc
de
ef
6
ab
bc
de
ef
gh
hi
樣例輸出
3
2
5
9
提示
In third case, there are $ 5 $ acceptable plans:
- (ab)(bc)(de)(ef)
- (ab)(bc)(de, ef)
- (ab, bc)(de)(ef)
- (ab, bc)(de, ef)
- (ab, bc, de, ef)
In fourth case, there are $ (2^3+1) $ acceptable plans.
來源
PKU Campus 2018
題目大意
給定一張無向完全圖,把它分成幾個連通塊,使得:
每個連通塊內部點之間的距離 $ < $ 該連通塊的與其他連通塊的點的距離
求劃分方案數
$ N \le 400 $
註:無向圖是通過若幹字符串及其編輯距離產生的
題解
對無向圖模擬一遍 $ Kruskal $ ,設 $ F(S) $ 表示集合 $ S $ 劃分滿足要求的連通塊的方案數
合並兩個集合 $ S_x,S_y $ 時:
若分別屬於 $ S_x, S_y $ 的點要分在同一連通塊,則 $ S_x \cup S_y $ 只能整個構成連通塊
若 $ S_x \cup S_y $ 滿足題目要求,則 $ F( S_x \cup S_y )=F(S_x) \times F(S_y) +1 $
否則 $ F( S_x \cup S_y )=F(S_x) \times F(S_y) $
代碼
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define mod 1000000007
#define int long long
#define maxm 200000
struct edge{ int u,v,w; }e[maxm];
int t,n,dis[500][500],c[25][25],f[500],cnt,ans,tot,F[500],pot[500][500];
string s[500];
bool cmp(edge x,edge y){ return x.w<y.w; }
int LCS(string x,string y){
int xlen=x.size(),ylen=y.size();
for(int i=1;i<=xlen;++i) c[i][0]=0;
for(int i=1;i<=ylen;++i) c[0][i]=0;
for(int i=1;i<=xlen;++i)
for(int j=1;j<=ylen;++j)
if(x[i-1]==y[j-1]) c[i][j]=c[i-1][j-1]+1;
else c[i][j]=max(c[i][j-1],c[i-1][j]);
return c[xlen][ylen];
}
int find(int x){
if(f[x]!=x) f[x]=find(f[x]);
return f[x];
}
bool check(int u){
int minn=mod,maxn=-mod;
for(int fu,fv,i=1;i<=cnt;++i){
fu=find(e[i].u); fv=find(e[i].v);
if(fu==u&&fv==u) maxn=max(maxn,e[i].w);
else if((fv==u&&fu!=u)||(fv!=u&&fu==u))
minn=min(minn,e[i].w);
}
return maxn<minn;
}
signed main(){
scanf("%lld",&t);
while(t--){
scanf("%lld",&n);
cnt=tot=0;
for(int i=1;i<=n;++i){ cin>>s[i]; f[i]=i; F[i]=1; }
for(int i=1;i<=n;++i)
for(int j=i+1;j<=n;++j){
e[++cnt].u=i; e[cnt].v=j;
e[cnt].w=dis[i][j]=dis[j][i]=s[i].size()+s[j].size()-2*LCS(s[i],s[j]);
}
sort(e+1,e+1+cnt,cmp);
for(int fu,fv,i=1;i<=cnt;++i){
fu=find(e[i].u); fv=find(e[i].v);
if(fu==fv) continue;
f[fu]=fv;
F[fv]=F[fu]*F[fv]%mod;
if(check(fv)) F[fv]=(F[fv]+1)%mod;
++tot; if(tot==n-1){ ans=F[fv]; break; }
}
printf("%lld\n",ans%mod);
}
return 0;
}
PKUACM 2018 D Chocolate 最小生成樹 Kruskal 最長公共子序列