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 }
View Code
原文地址:https://www.cnblogs.com/lawyer/p/6595721.html