巡邏-樹的直徑的3種求法
阿新 • • 發佈:2018-11-06
1.最樸素的求法:
列舉每一個點作為起點找到離它最遠的那個點(dfs),取每個點的最長路徑的max
時間複雜度: O(n*n)
程式碼這裡不貼咯
2.樹形dp
對於點作為根,它的最長路徑是他的最長路徑和次長路徑的和。所以對數進行樹形dp:dp[x][0]->最長, dp[x][1]->次長。
dp[x][1]+dp[x][0]即為以此點為根的最長路徑。
#include <iostream> #include <cstdio> #include <vector> using namespace std; const int maxn=100005; struct node { int w,v; }; vector<node> v[maxn]; node tmp;int ans=0; int f[maxn][2]; void find(int x,int fa) { for(int i=0;i<v[x].size();i++) { int w=v[x][i].w;int p=v[x][i].v; if(p==fa) continue; find(p,x); if(f[p][0]+w>f[x][0]) { f[x][1]=f[x][0]; f[x][0]=f[p][0]+w; } else if(f[p][0]+w>f[x][1]) f[x][1]=f[p][0]+w; } ans=max(ans,f[x][1]+f[x][0]); } int main() { int n,k;scanf("%d%d",&n,&k); for(int i=1;i<n;i++) { int a,b;scanf("%d%d",&a,&b); tmp.w=1;tmp.v=b; v[a].push_back(tmp); tmp.v=a;v[b].push_back(tmp); } find(1,0); printf("%d",(n-1-ans)*2+ans+1); return 0; }
3.先任意以一個點為根,找到離他最遠的點,然後這個點必定是直徑一個端點,以它為端點進行dfs(bfs)到的最遠點必定為樹的直徑。
void find(int x,int fa,int dep) { if(maxv<dep) {maxv=dep;u=x;} for(int i=0;i<v[x].size();i++) { if(v[x][i].v!=fa) find(v[x][i].v,x,dep+v[x][i].w); } } void bfs(int s) { q.push(s); //vis[s]=1; f[s]=0; while(!q.empty()) { int x=q.front(); q.pop(); for(int i=0;i<v[x].size();i++) { int tmp=v[x][i].v; if(tmp!=f[x]) { f[tmp]=x; q.push(tmp); deep[tmp]=deep[x]+1; //maxv=max(maxv,deep[tmp]); if(maxv<deep[tmp]) { maxv=deep[tmp];t=tmp; } } } } }