• 作者:老汪软件技巧
  • 发表时间:2024-01-04 21:00
  • 浏览量:

树的直径

树上最远两点(叶子结点)的距离。这里推荐dfs求树的直径。

性质 Cow

模板题,让你求距离最远的两个节点的距离,那么就是树的直径。树的直径怎么求,首先随便从一点u开始搜索找到离他最远的点t1,再从该点t1,搜索出离t1最远的点t2,t1跟t2就是树上最远两点。详细证明参考这篇博客传送门

下面展示一些 内联代码片。

#include 
using namespace std;
const int N = 4e4 + 5;
struct E {
	int to, nex, w;
}e[N << 1];
int cnt, head[N];
void Add(int u, int v, int w) {
	e[++cnt].to = v;
	e[cnt].w = w;
	e[cnt].nex = head[u];
	head[u] = cnt;
}
int mxd, mxu, t1, t2; 
void dfs(int u, int fa, int d) {
	if(d > mxd) { 
		mxd = d; //update deep
		mxu = u; //update id
	}
	for(int i = head[u]; i; i = e[i].nex) {
		int v = e[i].to, w = e[i].w;
		if(v == fa) continue;
		dfs(v, u, d + w);
	}
}
void solve() {
	int n, m, u, v, w;
	char c;
	cin >> n >> m;
	for(int i = 1; i <= m; ++i) {
		cin >> u >> v >> w >> c;
		Add(u, v, w), Add(v, u, w);
	}
	dfs(1, -1, 0); //from node 1 find
	mxd = 0;
	t1 = mxu;
	dfs(mxu, -1, 0);
	t2 = mxu;
	cout << mxd;
}
int main() {
	solve();
}

求出所有节点离他最远的节点距离。

#include 
#include 
#define rep(i, a, b) for(int i = a; i <= b; ++i)
using namespace std;
const int N = 1e4 + 10;
int cnt, head[N];
struct E {
    int to, nex, w;
}e[N << 1];
void Add(int u, int v, int w) { 
    e[++cnt].nex = head[u];
    e[cnt].to = v;
    e[cnt].w = w;  
    head[u] = cnt;
}
int n, mxd, mxu, t1, t2, dis[2][N];
void dfs1(int u, int fa, int d) {
    if(d > mxd) {
        mxd = d, mxu = u;
    }
    for(int i = head[u]; i; i = e[i].nex) {
        int v = e[i].to;
        if(v == fa) continue;
        dfs1(v, u, d + e[i].w);
    }
}
void dfs2(int u, int fa, int d, int p) {
    dis[p][u] = d;
    for(int i = head[u]; i; i = e[i].nex) {
        int v = e[i].to;
        if(v == fa) continue;
        dfs2(v, u, d + e[i].w, p);
    }
}
int main() {
    while(cin >> n) {
        cnt = 0;
        rep(i, 0, n) head[i] = 0;
        rep(i, 0, n) dis[0][i] = dis[1][i] = 0;
        rep(i, 2, n) {
            int u, w;
            cin >> u >> w;
            Add(u, i, w), Add(i, u, w);
        }
        mxd = mxu = 0;
        dfs1(1, -1, 0);
        t1 = mxu;
        mxd = mxu = 0;
        dfs1(t1, -1, 0);
        t2 = mxu;
        dfs2(t1, -1, 0, 0);
        dfs2(t2, -1, 0, 1);
        rep(i, 1, n) cout << max(dis[0][i], dis[1][i]) << "\n";
    }
    return 0;
}

F -

传送门

相距更远的两个点,fff值更大,求直径最远标记的两个点的中点距离就是答案。

#include 
#define int long long 
#define pii pair
#define debug(a) cout << #a << "=" << a <<"\n";
#define ios ios::sync_with_stdio(false), cin.tie(0);
#define rep(i, a, b) for(int i = a;i <= b; ++i)
#define multi int t;cin >> t;for(int i = 1;i <= t; ++i) solve()
using namespace std; 
const int N = 2e5 + 10;
struct node {
	int to, nex;
}e[N << 1];
int cnt, head[N];
void Add(int u, int v) {
	e[++cnt].nex = head[u];
	e[cnt].to = v;
	head[u] = cnt;
}
int n, m, a[N], f[N];
map mp;
int mxd, mxu;
void dfs(int u, int fa, int d) {
	if(d > mxd && mp[u]) {
		mxu = u;
		mxd = d;
	}
	for(int i = head[u]; i; i = e[i].nex) {
		int v = e[i].to;
		if(v == fa) continue;
		dfs(v, u, d + 1);
	}
}
void solve() {
    cin >> n >> m;
    int x, st, u, v;
    mp.clear();
    mxd = cnt = 0;
    rep(i, 1, n) head[i] = 0;
    rep(i, 1, m) {
    	cin >> x, mp[x]++;
    	st = x; //start point
    }
    rep(i, 2, n) {
    	cin >> u >> v;
    	Add(u, v), Add(v, u);
    }
    if(m == 1) {
    	cout << "0\n";
    	return;
    }
    dfs(st, -1, 0);
    mxd = 0;
    dfs(mxu, -1, 0);
    cout << (mxd + 1) / 2 << '\n';
}
signed main() {
    ios;
    multi;
    return 0;
}