直径
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\n",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╮(╯▽╰)╭