POJ 樹的直徑和重心

2022-09-01 12:27:08 字數 4126 閱讀 7621

樹的直徑:(無根)樹上最長兩點間的最長路徑,兩次dfs即可,第一次dfs任選一點u,找到距離它最遠的點s,再從點s進行一次dfs,找到距離s最遠的點t,則s-t之間的路徑就是樹的直徑。證明:

#include#include#include#include#includetypedef long long ll;

using namespace std;

const int maxn=10005;

ll d[maxn];

struct ksd

g[maxn];

int vis[maxn];

int head[maxn],cnt;

void add(int u,int v,int len)

void dfs(int x)

return ;

}int main()

d[1]=0;

dfs(1);

int m;

ll s=0;

for(int i=1;i<=n;i++)

d[i]=0;

}dfs(m);

ll ans=0;

for(int i=1;i<=n;i++)

ans=max(ans,d[i]);

printf("%lld\n",ans);

}

#include#include#includeusing namespace std;

const int maxn=200005;

int n,m;

struct pg[maxn];

int head[maxn],d[maxn],vis[maxn];

int cnt=0;

void add(int u,int v,int len)

void dfs(int x)

return ;

}int main()

d[i]=0;

}dfs(m);

int ans=0;

for(int i=1;i<=n;i++)

ans=max(ans,d[i]);

// cout《給你一張無向圖,問你這張圖是否是乙個caterpillar,caterpillar必須滿足是乙個連通圖,無環,切存在一條路徑,使圖中所有的點距離該路徑上點的最小距離為1或0

易知改圖是一棵樹,首先並查集判斷是否聯通,先找到直徑,再判斷所有點距離直徑距離

#include#include#includeusing namespace std;

const int maxn=605;

int fa[maxn],head[maxn],d[maxn],ans[maxn],vis[maxn];

struct pg[maxn*2];

int mp[maxn][maxn];

int fi(int x)

int cnt=0;

void add(int u,int v)

void dfs(int x)

return ;

}int n,m,p,q,k=0;

bool dfs(int z)

vis[z]=1;

for(int i=head[z];i;i=g[i].next)

}return false;

}int main()

scanf("%d",&m);

bool f=1;

if(m!=n-1)

f=0;

for(int i=1;i<=m;i++)

for(int i=1;i<=n;i++)

if(fi(i)!=fi(1))

if(f==0)

dfs(1);

int s=0;

for(int i=1;i<=n;i++)

d[i]=0;

}dfs(p);

s=0;

for(int i=1;i<=n;i++)

d[i]=0;

}dfs(p);

for(int i=1;i<=n;i++)

if(j>n)}}

if(f==0)

else printf("graph %d is a caterpillar.\n",++cas);

}}

大雪將城鎮的街道覆蓋了,兩輛鏟雪機從同一城市出發,要求將所有街道得雪都鏟完,任意一輛鏟雪機可以鏟任意一條街道,最後兩輛車可以停在任意一處,問兩輛車的最少運動長度

有些道路可以經過一次,但有些街道需要經過兩次,那麼即找到一條最長的距離,車子只要走一趟,易知這條路徑即為直徑,故答案為所有邊的長度*2-直徑

#include#include#includeusing namespace std;

const int maxn=200005;

int n,m;

struct pg[maxn];

int head[maxn],d[maxn],vis[maxn];

int cnt=0;

void add(int u,int v,int len)

void dfs(int x)

return ;

}int main()

sum=sum*2;

d[1]=0;

dfs(1);

int m;

int s=0;

for(int i=1;i<=n;i++)

d[i]=0;

}dfs(m);

int ans=0;

for(int i=1;i<=n;i++)

ans=max(ans,d[i]);

// cout《給你一張圖,已知兩兩之間的距離為1,問你找出使距離某個點最遠距離最小的點,即找到直徑,若直徑上的點為奇數,則為中間的,若為偶數,則為中間兩個,注意輸入給的距離是讓我們建樹的

#include#include#include#includeusing namespace std;

const int maxn=10005;

int vis[maxn],head[maxn],cnt,v0[maxn];

struct pg[maxn];

struct qp[maxn];

int d[maxn],ans[maxn];

//int sum=0;

void add(int u,int v)

int ma; int n;

void dfs(int x)

return ;

}int q;

int l;

bool dfs(int z)

vis[z]=1;

for(int i=head[z];i;i=g[i].next)

}return false;

}int main()

for(int i=2;i<=n;i++)

d[k]=0;

}dfs(c);

s=0;

for(int i=1;i<=n;i++)

d[k]=0;

}dfs(c);

ans[++l]=c;

if(l%2==0)g[maxn];

void add(int u,int v)

int ma=1e9;

int n;

void dfs(int u)

if(n-d[u]>ans[u])

ans[u]=n-d[u];

if(ma>ans[u])

ma=ans[u];

}int main()

for(int i=1;i求樹的重心,輸出字典序最小的

#include#include#includeusing namespace std;

const int maxn=100005;

int cnt,d[maxn],vis[maxn],head[maxn];

struct pg[maxn];

void add(int u,int v)

int ans1,ans2;

int n;

void dfs(int u)

sum=max(sum,n-d[u]);

if((sum}int main()

for(int i=1;idfs(1);

printf("%d %d\n",ans1,ans2);

}}

樹的重心 樹的直徑

樹的重心 樹的重心定義為 找到乙個點,其所有的子樹中最大的子樹節點數最少,那麼這個點就是這棵樹的重心,刪去重心後,生成的多棵樹盡可能平衡.實際上樹的重心在樹的點分治中有重要的作用,可以避免n 2的極端複雜度 從退化鏈的一端出發 保證nlogn的複雜度,利用樹型dp可以很好地求樹的重心.求樹的重心 模...

樹的直徑 樹的重心

樹的直徑 定義 那麼樹上最遠的兩個點,他們之間的距離,就被稱之為樹的直徑。樹的直徑的性質 1.直徑兩端點一定是兩個葉子節點。2.距離任意點最遠的點一定是直徑的乙個端點,這個基於貪心求直徑方法的正確性 可以得出。3.對於兩棵樹,如果第一棵樹直徑兩端點為 u,v 第二棵樹直徑兩端點為 x,y 用條邊將兩...

樹的直徑與重心

樹的直徑,指樹上最長的不重複經過同乙個點的路徑。方法 先從任意一點p pp出發,找離它最遠的點q qq,再從點q qq出發,找離它最遠的點w ww,w ww到q qq的距離就是的直徑 具體實現可以使用兩次dfs dfsdf s。演算法證明 反證法 include using namespace st...