給你一棵
n 個點的樹,另外還有
m棵樹,第
i 棵樹與原樹的以ri
為根的子樹形態相同。這
m 棵樹之間也有連邊,組成一顆大樹。求這棵大樹的直徑長度。n,
m≤300000
我們先用dp求出以原樹的第
i 個點為根的子樹的直徑,那麼以原樹的第
i個點為根的子樹中的某個點為乙個端點的最長路的另乙個端點一定在直徑的一端。
然後我們遍歷第
i 棵樹與其他樹之間的邊,求出每個點走到其他樹的最長路。然後用虛樹把這些邊在第
i棵樹的端點和ri
連在一起,用dp合併。
zjt大爺:明明可以直接bfs兩次為什麼要dp?
時間複雜度:o(
(n+m
)logn)
#include
#include
#include
#include
#include
#include
using
namespace
std;
typedef
long
long ll;
typedef pair pii;
const
int maxn=1200010;
struct
list
void add(int x,int y)
};struct list2
void add(int a,int a2,int b,int b2)
};int n,m;
namespace tree
};int
operator
<(p3 a,p3 b)
void dfs(int x,int fa,int dep)
ti++;
w[ti]=x;
}ed[x]=ti;
}void buildst()
int getlca(int x,int y)
int getdist(int x,int y)
}list2 l2;
int r[maxn];
ll ans;
ll f[maxn];
intstack[maxn];
int top;
int c[maxn];
int par[maxn];
ll g[maxn];
int cnt;
int tag[maxn];
int dfscmp(int x,int y)
void pushup(int x)
void dp(int x,int x2,int fa)
else
}if(tag[x2]!=x)
sort(c+1,c+cnt+1,dfscmp);
cnt=unique(c+1,c+cnt+1)-c-1;
top=0;
int lca;
for(i=1;i<=cnt;i++)
int lca=tree::getlca(c[i],c[i-1]);
while(top&&tree::d[stack[top]]>tree::d[lca])
pushup(stack[top]);
top--;
}if(tree::d[stack[top]]stack[top];
stack[++top]=lca;
}par[c[i]]=stack[top];
stack[++top]=c[i];
}while(top)
}int main()
tree::dfs(1,0,1);
tree::buildst();
for(i=1;i<=m;i++)
scanf("%d",&r[i]);
for(i=1;iscanf("%d%d%d%d",&x,&x2,&y,&y2);
l2.add(x,x2,y,y2);
l2.add(y,y2,x,x2);
}ans=0;
dp(1,r[1],0);
printf("%lld\n",ans);
return
0;}
XSY1545 直徑 虛樹 DP
給你一棵 n 個點的樹,另外還有 m 棵樹,第 i 棵樹與原樹的以 r i 為根的子樹形態相同。這 m 棵樹之間也有連邊,組成一顆大樹。求這棵大樹的直徑長度。n,m leq 300000 我們先用dp求出以原樹的第 i 個點為根的子樹的直徑,那麼以原樹的第 i 個點為根的子樹中的某個點為乙個端點的最...
2334 樹的直徑(樹形DP)
原博主部落格 還有廣搜的寫法 描述 樹的直徑,即這棵樹中距離最遠的兩個結點的距離。每兩個相鄰的結點的距離為1,即父親結點與兒子結點或兒子結點與父子結點之間的距離為1.有趣的是,從樹的任意乙個結點a出發,走到距離最遠的結點b,再從結點b出發,能夠走的最遠距離,就是樹的直徑。樹中相鄰兩個結點的距離為1。...
樹形dp 求樹的直徑
隨著杭州西湖的知名度的進一步提公升,園林規劃專家湫湫希望設計出一條新的經典觀光線路,根據老闆馬小騰的指示,新的風景線最好能建成環形,如果沒有條件建成環形,那就建的越長越好。現在已經勘探確定了n個位置可以用來建設,在它們之間也勘探確定了m條可以設計的路線以及他們的長度。請問是否能夠建成環形的風景線?如...