您的位置:首页 > 其它

【2016北京集训测试赛(八)】 直径 (虚树+树的直径)

2017-08-14 19:17 381 查看

Description

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=300010,Bas=20;
int n,m,tot,bas,ho
,side
[3],pre
[Bas+1],dep
;
ll far[2];
int timecnt,dfn
,rt
,cnt,newid
,H[N*10];
vector<int> use
;
map<int,int> tree
;
struct Edge{int v,w,next;}g[N*2+N*20];
struct WaitEdge{
int a,b,c,d;
WaitEdge(){}
WaitEdge(int aa,int bb,int cc,int dd){a=aa;b=bb;c=cc;d=dd;}
void get(int &aa,int &bb,int &cc,int &dd){aa=a;bb=b;cc=c;dd=d;}
}waitedge
;
struct MT{
int a,as,b,bs;
MT(){a=as=b=bs=-1;}
void push(int c,int cs){
if(c>a)
b=a, bs=as,
a=c, as=cs;
else if(c>b)
b=c, bs=cs;
}
}mt
;
inline void addEdge(int u,int v,int w,int *h){
if(u==v) return;
g[++tot].v=v; g[tot].w=w; g[tot].next=h[u]; h[u]=tot;
}
void preDfs(int u,int fa,int deep){
dfn[u]=++timecnt;
dep[u]=deep;
pre[u][0]=fa;
for(int i=1;i<=bas;i++) pre[u][i]=pre[pre[u][i-1]][i-1];
for(int i=ho[u],v;i;i=g[i].next){
if((v=g[i].v)!=fa){
preDfs(v,u,deep+1);
mt[u].push(mt[v].a+1,mt[v].as);
if(side[v][0]&&side[v][0]>side[u][0])
side[u][0]=side[v][0],side[u][1]=side[v][1],side[u][2]=side[v][2];
}
}
mt[u].push(0,u);
if(mt[u].as!=-1&&mt[u].bs==-1){
side[u][0]=1;
side[u][1]=side[u][2]=u;
}
else
if(mt[u].as&&mt[u].bs&&mt[u].a+mt[u].b+1>side[u][0]){
side[u][0]=mt[u].a+mt[u].b+1;
side[u][1]=mt[u].as;
side[u][2]=mt[u].bs;
}
}
int getLca(int a,int b){
if(dep[a]<dep[b]) swap(a,b);
for(int i=bas;i>=0;i--)
if(dep[pre[a][i]]>=dep[b])
a=pre[a][i];
if(a==b) return a;
for(int i=bas;i>=0;i--)
if(pre[a][i]!=pre[b][i])
a=pre[a][i], b=pre[b][i];
return pre[a][0];
}
bool cmp(int x,int y){return dfn[x]<dfn[y];}
int lis[N*10],K,st[N*10],top,tms[N*10];
void build(int id){
int u=rt[id],vsiz=use[id].size();
K=3;
lis[1]=u; lis[2]=side[u][1]; lis[3]=side[u][2];
for(int i=0;i<vsiz;i++) lis[++K]=use[id][i];
sort(lis+1,lis+1+K);
K=unique(lis+1,lis+1+K)-lis-1;
sort(lis+1,lis+1+K,cmp);
for(int i=1;i<=K;i++) newid[lis[i]]=++cnt,tms[lis[i]]=id;
if(K>1){
st[1]=lis[1]; st[2]=lis[2];
top=2;
for(int i=3;i<=K;i++){
int now=lis[i],lca=getLca(now,st[top]);
while(1){
if(dep[lca]>=dep[st[top-1]]){
if(tms[lca]!=id) newid[lca]=++cnt,tms[lca]=id;
addEdge(newid[lca],newid[st[top]],dep[st[top]]-dep[lca],H);
addEdge(newid[st[top]],newid[lca],dep[st[top]]-dep[lca],H);
top--;
if(st[top]!=lca) st[++top]=lca;
break;
}
addEdge(newid[st[top-1]],newid[st[top]],dep[st[top]]-dep[st[top-1]],H);
addEdge(newid[st[top]],newid[st[top-1]],dep[st[top]]-dep[st[top-1]],H);
top--;
}
if(st[top]!=now)
st[++top]=now;
}
for(;top>1;top--){
addEdge(newid[st[top]],newid[st[top-1]],dep[st[top]]-dep[st[top-1]],H);
addEdge(newid[st[top-1]],newid[st[top]],dep[st[top]]-dep[st[top-1]],H);
}
}
for(int i=1;i<=K;i++)
tree[id][lis[i]]=newid[lis[i]];
}
void dfs(int u,int fa,ll dis){
if(dis>far[0])
far[0]=dis,
far[1]=u;
for(int i=H[u],v;i;i=g[i].next)
if((v=g[i].v)!=fa)
dfs(v,u,dis+g[i].w);
}
int main(){
scanf("%d%d",&n,&m);
bas=((int)log2(n))+1;
for(int i=1,x,y;i<n;i++)
scanf("%d%d",&x,&y),
addEdge(x,y,1,ho),addEdge(y,x,1,ho);
preDfs(1,0,1);
for(int i=1,x;i<=m;i++)
scanf("%d",&rt[i]);
for(int i=1,a,b,c,d;i<m;i++){
scanf("%d%d%d%d",&a,&b,&c,&d);
waitedge[i]=WaitEdge(a,b,c,d);
use[a].push_back(b);
use[c].push_back(d);
}
for(int i=1;i<=m;i++)
build(i);
for(int i=1;i<m;i++){
int a,b,c,d,x,y;
waitedge[i].get(a,b,c,d);
x=tree[a][b]; y=tree[c][d];
addEdge(x,y,1,H); addEdge(y,x,1,H);
}
dfs(tree[1][rt[1]],0,1);
int t=far[1];
far[0]=far[1]=0;
dfs(t,0,1);
printf("%lld\n",far[0]);
return 0;
}


奇妙代码

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: