Acyclic Organic Compounds
题意:
给一以1为根的字符树,给出每个节点的字符与权值,记 $diff_{x}$ 为从 $x$ 出发向下走,能走到多少不同的字符串,求问最大的
$diff_{x} + c_{x}$,并求有多少个 $diff_{x} + c_{x}$。
解法:
考虑$dfs$,从下到上启发式合并 $Trie$ 树,效率 $O(nlogn)$。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 #define N 300010 6 7 using namespace std; 8 9 struct edge 10 { 11 int x,to; 12 }E[N<<1]; 13 14 struct node 15 { 16 node *ch[26]; 17 int siz; 18 19 node* init() 20 { 21 siz=1; 22 memset(ch,0,sizeof(ch)); 23 return this; 24 }; 25 }spT[N<<1],*root[N]; 26 27 int n,m,totn,totE,ans,ansv; 28 int fa[N],g[N],c[N]; 29 char S[N]; 30 31 void addedge(int x,int y) 32 { 33 E[++totE] = (edge){y,g[x]}; g[x]=totE; 34 E[++totE] = (edge){x,g[y]}; g[y]=totE; 35 } 36 37 #define p E[i].x 38 39 node* merge(node *p1,node *p2) 40 { 41 if(p1->siz < p2->siz) swap(p1,p2); 42 for(int t=0;t<26;t++) 43 if(p2->ch[t]) 44 { 45 if(!p1->ch[t]) p1->ch[t]=p2->ch[t]; 46 else p1->ch[t] = merge(p1->ch[t], p2->ch[t]); 47 } 48 p1->siz=1; 49 for(int t=0;t<26;t++) 50 if(p1->ch[t]) p1->siz+=p1->ch[t]->siz; 51 return p1; 52 } 53 54 void dfs(int x) 55 { 56 int tmp=S[x]-'a'; 57 root[x]=spT[++totn].init(); 58 root[x]->ch[tmp]=spT[++totn].init(); 59 for(int i=g[x];i;i=E[i].to) 60 if(p!=fa[x]) 61 { 62 fa[p]=x; 63 dfs(p); 64 } 65 for(int i=g[x];i;i=E[i].to) 66 if(p!=fa[x]) 67 root[x]->ch[tmp] = merge(root[x]->ch[tmp],root[p]); 68 root[x]->siz = root[x]->ch[tmp]->siz; 69 if(root[x]->siz+c[x] > ansv) 70 { 71 ansv = root[x]->siz+c[x]; 72 ans=1; 73 } 74 else if(root[x]->siz+c[x] == ansv) ans++; 75 } 76 77 int main() 78 { 79 while(~scanf("%d",&n)) 80 { 81 for(int i=1;i<=n;i++) g[i]=0; 82 totE=0; 83 for(int i=1;i<=n;i++) scanf("%d",&c[i]); 84 S[0]='*'; 85 scanf("%s",S+1); 86 ans=0; 87 totn=ansv=0; 88 for(int i=1,x,y;i<n;i++) 89 { 90 scanf("%d%d",&x,&y); 91 addedge(x,y); 92 } 93 fa[1]=0; 94 dfs(1); 95 cout << ansv << endl << ans << endl; 96 } 97 return 0; 98 }