直径

Description

小明在花园里种了一棵树,并把它的根标号为1。小明还嫌这棵树太小,因此自己又种了m棵小树,这些小树都与大树的某个树枝相同(即是原树的一棵子树)。现在,小明又把这m棵小树拼接起来,形成一棵大树,最后,小明想知道如果自己从树的一个节点爬到另一个节点最多能经过多少个节点(包括首尾两个节点)。

Input

输入文件的第一行是两个正整数n和m,分别表示原树的节点个数和小明新种的树的个数。

接下去n-1行每行有两个正整数a和b,表示原树中有一条连接a点和b点的边。

第n+1行有m个正整数r1,…,rm,其中ri表示第i棵小树与原树中以i为根的子树相等(节点号也是相等的)。

最后m-1行,每行有4个正整数a,b,c,d,表示第a棵树的b号节点与第c棵树的d号节点之间有一条边相连。保证b号节点在子树a内且d号节点在子树c内。

Output

输出一个数,表示树的最长链长度。

Sample Input

3 3

1 2

1 3

1 2 3

1 3 2 2

1 2 3 3

Sample Output

5

Hint

对于100%的数据,1≤n,m≤300000。


Solution

由题目可得,这道题就是求一棵树的直径。

如果是暴力求直径,时间复杂度和空间复杂度最坏将达到O(n2)。因此,我们考虑建一棵虚树,仅保留重要的点(子树的根节点,直径的两端,与其它小树的连接点以及前面几项中点的lca)。

由于每棵小树都对应着原树中的某棵子树,我们可以在原树中跑一次树形dp,求出每棵子树的直径。时间复杂度O(n)。

在树形dp中我们可以顺便求出每个点的dfn值用于建虚树。建虚树时注意要赋予新的节点编号。我们可以用map来判断某个节点是否已经被取到。建立虚树前将所有重要点(不包含lca,在建树时才加入)按dfn的大小排序。时间复杂度O(nlogn)。

建好虚树后在虚树上再跑一次树形dp求出直径。时间复杂度O(n)。

总的时间复杂度为O(nlogn)。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<vector>
  5 #include<map>
  6 #include<stack>
  7 #include<queue>
  8 using namespace std;
  9 #define next _next
 10 struct edge{
 11     int to,next;
 12 }e[600010]={0};
 13 struct Edge{
 14     int a,b,c,d;
 15 }E[300010];
 16 struct point{
 17     int dfn,dep,fa[20];
 18     int dx,dy,dist;
 19     int mx[2],p[2];
 20 }p[300010]={0};
 21 int n,m,cnt=-1,tcnt=-1,head[300010];
 22 int root[300010];
 23 vector<int>vec[300010];
 24 namespace Vtree{
 25     #define pa pair<int,int>
 26     #define id1(x,y) make_pair(x,y)
 27     #define id2(x) make_pair(p[x].dfn,x)
 28     struct vtree{
 29         int to,next,data;
 30     }ve[6000010]={0};
 31     struct vpoint{
 32         long long dist,mx[2];
 33     }vp[6000010]={0};
 34     int tot=0,vcnt=-1,vhead[6000010];
 35     priority_queue<pa,vector<pa>,greater<pa> >q;
 36     stack<pa>stk;
 37     map<pa,int>mp;
 38     void Init(){
 39         memset(vhead,-1,sizeof(vhead));
 40         mp.clear();
 41         return;
 42     }
 43     void Addedge(int u,int v,int w){
 44         ve[++vcnt]=(vtree){v,vhead[u],w};
 45         vhead[u]=vcnt;
 46         return;
 47     }
 48     int LCA(int u,int v){
 49         if(p[u].dep<p[v].dep)
 50             swap(u,v);
 51         int delta=p[u].dep-p[v].dep;
 52         for(int i=0;i<20;i++)
 53             if(delta&(1<<i))
 54                 u=p[u].fa[i];
 55         for(int i=19;~i;i--)
 56             if(p[u].fa[i]!=p[v].fa[i]){
 57                 u=p[u].fa[i];
 58                 v=p[v].fa[i];
 59             }
 60         return (u==v)?u:p[u].fa[0];
 61     }
 62     void Build(int x){
 63         while(!q.empty())
 64             q.pop();
 65         while(!stk.empty())
 66             stk.pop();
 67         mp[id1(x,root[x])]=++tot;
 68         q.push(id2(root[x]));
 69         if(p[root[x]].dx&&!mp[id1(x,p[root[x]].dx)]){
 70             mp[id1(x,p[root[x]].dx)]=++tot;
 71             q.push(id2(p[root[x]].dx));
 72         }
 73         if(p[root[x]].dy&&!mp[id1(x,p[root[x]].dy)]){
 74             mp[id1(x,p[root[x]].dy)]=++tot;
 75             q.push(id2(p[root[x]].dy));
 76         }
 77         for(int i=0;i<vec[x].size();i++)
 78             if(!mp[id1(x,vec[x][i])]){
 79                 mp[id1(x,vec[x][i])]=++tot;
 80                 q.push(id2(vec[x][i]));
 81             }
 82         if(q.size()<2)
 83             return;
 84         stk.push(q.top());
 85         q.pop();
 86         stk.push(q.top());
 87         q.pop();
 88         while(!q.empty()){
 89             pa u=q.top();
 90             q.pop();
 91             int lca=LCA(u.second,stk.top().second);
 92             if(lca==stk.top().second)
 93                 stk.push(u);
 94             else{
 95                 int last=0;
 96                 while(!stk.empty()&&stk.top().first>p[lca].dfn){
 97                     if(last){
 98                         int xx=last,yy=stk.top().second;
 99                         Addedge(mp[id1(x,xx)],mp[id1(x,yy)],p[xx].dep-p[yy].dep);
100                         Addedge(mp[id1(x,yy)],mp[id1(x,xx)],p[xx].dep-p[yy].dep);
101                     }
102                     last=stk.top().second;
103                     stk.pop();
104                 }
105                 if(!mp[id1(x,lca)]){
106                     mp[id1(x,lca)]=++tot;
107                     stk.push(id2(lca));
108                 }
109                 Addedge(mp[id1(x,last)],mp[id1(x,lca)],p[last].dep-p[lca].dep);
110                 Addedge(mp[id1(x,lca)],mp[id1(x,last)],p[last].dep-p[lca].dep);
111                 stk.push(u);
112             }
113         }
114         int last=0;
115         while(!stk.empty()){
116             if(last){
117                 int xx=last,yy=stk.top().second;
118                 Addedge(mp[id1(x,xx)],mp[id1(x,yy)],p[xx].dep-p[yy].dep);
119                 Addedge(mp[id1(x,yy)],mp[id1(x,xx)],p[xx].dep-p[yy].dep);
120             }
121             last=stk.top().second;
122             stk.pop();
123         }
124         return;
125     }
126     void Build_Vtree(){
127         for(int i=1;i<=m;i++)
128             Build(i);
129         for(int i=1;i<m;i++){
130             Addedge(mp[id1(E[i].a,E[i].b)],mp[id1(E[i].c,E[i].d)],1);
131             Addedge(mp[id1(E[i].c,E[i].d)],mp[id1(E[i].a,E[i].b)],1);
132         }
133         return;
134     }
135     void Dfs(int u,int fa){
136         for(int i=vhead[u];~i;i=ve[i].next){
137             int v=ve[i].to;
138             if(v==fa)
139                 continue;
140             Dfs(v,u);
141             if(vp[u].mx[0]<vp[v].mx[0]+ve[i].data){
142                 vp[u].mx[1]=vp[u].mx[0];
143                 vp[u].mx[0]=vp[v].mx[0]+ve[i].data;
144             }
145             else if(vp[u].mx[1]<vp[v].mx[0]+ve[i].data)
146                 vp[u].mx[1]=vp[v].mx[0]+ve[i].data;
147             if(vp[u].dist<vp[v].dist)
148                 vp[u].dist=vp[v].dist;
149         }
150         vp[u].dist=max(vp[u].dist,vp[u].mx[0]+vp[u].mx[1]);
151         return;
152     }
153     void Solve(){
154         Dfs(1,0);
155         printf("%lld
",vp[1].dist+1);
156         return;
157     }
158     #undef pa
159     #undef id1
160     #undef id2
161 }
162 void Dfs(int u,int fa,int dep){
163     p[u].dfn=++tcnt;
164     p[u].dep=dep;
165     p[u].fa[0]=fa;
166     for(int i=1;(1<<i)<p[u].dep;i++)
167         p[u].fa[i]=p[p[u].fa[i-1]].fa[i-1];
168     for(int i=head[u];~i;i=e[i].next){
169         int v=e[i].to;
170         if(v==fa)
171             continue;
172         Dfs(v,u,dep+1);
173         if(p[u].mx[0]<p[v].mx[0]+1){
174             p[u].mx[1]=p[u].mx[0];
175             p[u].p[1]=p[u].p[0];
176             p[u].mx[0]=p[v].mx[0]+1;
177             p[u].p[0]=p[v].p[0];
178         }
179         else if(p[u].mx[1]<p[v].mx[0]+1){
180             p[u].mx[1]=p[v].mx[0]+1;
181             p[u].p[1]=p[v].p[0];
182         }
183         if(p[u].dist<p[v].dist){
184             p[u].dist=p[v].dist;
185             p[u].dx=p[v].dx;
186             p[u].dy=p[v].dy;
187         }
188     }
189     if(!p[u].mx[0]){
190         p[u].p[0]=u;
191         p[u].dist=0;
192         p[u].dx=p[u].dy=u;
193     }
194     else if(!p[u].mx[1]){
195         if(p[u].mx[0]>p[u].dist){
196             p[u].dist=p[u].mx[0];
197             p[u].dx=u;
198             p[u].dy=p[u].p[0];
199         }
200     }
201     else if(p[u].mx[0]+p[u].mx[1]>p[u].dist){
202         p[u].dist=p[u].mx[0]+p[u].mx[1];
203         p[u].dx=p[u].p[0];
204         p[u].dy=p[u].p[1];
205     }
206     return;
207 }
208 void Addedge(int u,int v){
209     e[++cnt]=(edge){v,head[u]};
210     head[u]=cnt;
211     return;
212 }
213 void Init(){
214     memset(head,-1,sizeof(head));
215     for(int i=1;i<=300000;i++)
216         vec[i].clear();
217     return;
218 }
219 void Read(){
220     scanf("%d%d",&n,&m);
221     for(int i=1;i<n;i++){
222         int u,v;
223         scanf("%d%d",&u,&v);
224         Addedge(u,v);
225         Addedge(v,u);
226     }
227     for(int i=1;i<=m;i++)
228         scanf("%d",root+i);
229     for(int i=1;i<m;i++){
230         int a,b,c,d;
231         scanf("%d%d%d%d",&a,&b,&c,&d);
232         E[i]=(Edge){a,b,c,d};
233         vec[a].push_back(b);
234         vec[c].push_back(d);
235     }
236     return;
237 }
238 void Solve(){
239     Dfs(1,0,1);
240     Vtree::Init();
241     Vtree::Build_Vtree();
242     Vtree::Solve();
243     return;
244 }
245 int main(){
246     Init();
247     Read();
248     Solve();
249     return 0;
250 }

↑我的代码常数炸了,勉强卡进4s╮(╯▽╰)╭

原文地址:https://www.cnblogs.com/gzez181027/p/diameter.html