1. 程式人生 > >【CF778C】Peterson Polyglot(Trie樹,啟發式合併)

【CF778C】Peterson Polyglot(Trie樹,啟發式合併)

題意:有一棵n個結點的只由小寫字母組成的Trie樹,給定它的具體形態,問刪除哪一層後剩下Trie樹的結點數最少

n<=3e5

思路:先建出原Trie樹,對於每一層的每一個結點計算刪除後對答案的貢獻,這一部分使用啟發式合併

官方題解證明了時間複雜度是一個log的

http://codeforces.com/blog/entry/50724

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 typedef long
long ll; 6 using namespace std; 7 #define N 310000 8 9 int map[N][27],head[N],vet[N<<1],nxt[N<<1],size[N],dep[N],ans[N],flag[N], 10 n,cnt,tot; 11 12 char len[N<<1],ch[10]; 13 14 void add(int a,int b,char c) 15 { 16 nxt[++tot]=head[a]; 17 vet[tot]=b; 18 len[tot]=c;
19 head[a]=tot; 20 } 21 22 int merge(int x,int y) 23 { 24 if(!x||!y) return x+y; 25 int t=++cnt; 26 size[t]=1; 27 for(int i=1;i<=26;i++) 28 { 29 map[t][i]=merge(map[x][i],map[y][i]); 30 size[t]+=size[map[t][i]]; 31 } 32 return t; 33 } 34 35 void dfs(int
u) 36 { 37 size[u]=flag[u]=1; 38 int e=head[u]; 39 while(e) 40 { 41 int v=vet[e]; 42 if(!flag[v]) 43 { 44 dep[v]=dep[u]+1; 45 map[u][len[e]-'a'+1]=v; 46 dfs(v); 47 size[u]+=size[v]; 48 } 49 e=nxt[e]; 50 } 51 ans[dep[u]]+=size[u]; 52 cnt=n; 53 int t=0; 54 for(int i=1;i<=26;i++) t=merge(t,map[u][i]); 55 ans[dep[u]]-=max(size[t],1); 56 } 57 58 int main() 59 { 60 scanf("%d",&n); 61 for(int i=1;i<=n-1;i++) 62 { 63 int x,y; 64 scanf("%d%d%s",&x,&y,ch); 65 add(x,y,ch[0]); 66 add(y,x,ch[0]); 67 } 68 memset(flag,0,sizeof(flag)); 69 dfs(1); 70 int k=0; 71 for(int i=0;i<=n-1;i++) 72 if(ans[k]<ans[i]) k=i; 73 printf("%d\n",n-ans[k]); 74 printf("%d\n",k+1); 75 return 0; 76 }