Universal Travel Graph Theory - Diameter

Topic Link

Subject description:

There are n points n-1 communication by the edges, if an edge is removed, the diameter is the smallest number in FIG.

Enter a description:

The first line of a positive integer n-(n-<= 10 . 6 ), represents the number of points. And these points are numbered from 1 to n.
Next, n-1 lines, each line three positive integers a, b, w. That number is a number of points and has a length between the point b is w (w <= 1000) side.

Output Description:

Enter an integer line to meet the requirements in question.

In order to remove the rear edge of a minimum diameter, we will choose the picture on the diameter of an edge is removed. Enumeration removed on each edge and update the minimum diameter, it should be noted that every time we have to enumerate the calculated diameter, will certainly be overrun time, so we find a way to get these in advance and stored in diameter.

Then there is the solution to the problem:
First of all, to master two methods to solve the general diameter (twice dfs, tree dp)
Method One: twice dfs (NOTE: This method can be obtained at both ends of the diameter of the point L, R
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const int N = 1e5 + 1;

struct edge { //链式前向星 
	int to, next, w; edge(){}
	edge(int a,int b,int c):to(a),next(b),w(c){}
}e[N << 1]; int tot, head[N]; 

int d[N];// 记录节点到根的距离 
void dfs(int x, int pre, int &lr) {
	if (d[lr] < d[x]) lr = x;
	for(int i = head[x]; i != -1; i = e[i].next) {
		int to = e[i].to;
		if (to == pre) continue;
		d[to] = d[x] + e[i].w;
		dfs(to, x, lr);
	}
}

int main() {
	int n; scanf("%d", &n);
	memset(head, -1, sizeof(head));
	for(int i = 1; i < n; ++i) {
		int x,y,k; scanf("%d%d%d", &x, &y, &k);
		e[++tot]=edge(y,head[x],k),head[x]=tot; 
		e[++tot]=edge(x,head[y],k),head[y]=tot; 
	}
	int l,r; dfs(1,0,l=1); d[l]=0;dfs(l,0,r=l);
	printf("%d\n", d[r]);
	return 0;
}
Method two: tree DP (Added: you can get all the sub-diameter trees
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const int N = 1e5 + 1;

struct edge { //链式前向星 
	int to, next, w; edge(){}
	edge(int a,int b,int c):to(a),next(b),w(c){}
}e[N << 1]; int tot, head[N]; 

int f1[N], f2[N];// 以i为根的直径和最长链 
void dp(int x, int pre) {// 树形dp 
	for(int i = head[x]; i != -1; i = e[i].next) {
 		int to = e[i].to;
 		if (to == pre) continue;// 防止回头 
 		dp(to, x);
 		f1[x] = max(f1[x], max(f1[to], f2[x] + f2[to] + e[i].w));
 		if (f2[x] < f2[to] + e[i].w) f2[x] = f2[to] + e[i].w;
 	}
}

int main() {
	int n; scanf("%d", &n);
	memset(head, -1, sizeof(head));
	for(int i = 1; i < n; ++i) {
		int x,y,k; scanf("%d%d%d", &x, &y, &k);
		e[++tot]=edge(y,head[x],k),head[x]=tot; 
		e[++tot]=edge(x,head[y],k),head[y]=tot; 
	} 
	dp(1, 0); printf("%d\n", f1[1]);
	return 0;
}

The two methods are complementary, we can combine them to record the root diameter L all its subtree, then R empathy for the root diameter of the recording of all its sub-tree, and finally when we enumerate Analyzing and diameter can be directly updated. Specific code as follows:

#include<cstdio>
#include<cstring>
#include<algorithm> 

using namespace std;

const int  N  = 1e6+1;
const int inf = 0x3f3f3f3f;

template<class T> inline void read(T &x,int xk=10) { // quick read 
	char ch = getchar();T f = 1;
	for(x =0;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') f=-1;
	for(;ch<='9'&&ch>='0';ch=getchar()) x=x*xk+ch-'0';x*=f;
}

struct edge { //链式前向星 
	int to, next, w; edge(){}
	edge(int a,int b,int c):to(a),next(b),w(c){}
}e[N << 1]; int tot, head[N]; 

int d[N],f1[N],f2[N],D[N],res = inf;

void dfs(int x, int pre, int &lr) {
	if (d[lr] < d[x]) lr = x;
	for(int i = head[x]; i != -1; i = e[i].next) {
		int to = e[i].to;
		if (to == pre) continue;
		d[to] = d[x] + e[i].w;
		dfs(to, x, lr);
	} 
}

void dpl(int x, int pre) {
	for(int i = head[x]; i != -1; i = e[i].next) {
		int to = e[i].to;
		if (to == pre) continue;
		dpl(to, x);
		f1[x]=max(f1[x],max(f1[to],f2[x]+f2[to]+e[i].w));
		if (f2[x]<f2[to]+e[i].w) f2[x] = f2[to] + e[i].w;
		if (D[x] < f1[x]) D[x] = f1[x]; 
	}
}

void dpr(int x, int pre) {
	for(int i = head[x]; i != -1; i = e[i].next) {
		int to = e[i].to;
		if (to == pre) continue;
		dpr(to, x);
		f1[x]=max(f1[x],max(f1[to],f2[x]+f2[to]+e[i].w));
		if (f2[x]<f2[to]+e[i].w) f2[x] = f2[to] + e[i].w;
		if (D[pre] < f1[x]) D[pre] = f1[x]; 
	}
}

bool Dfs(int x, int pre, int y) {
	if (x == y) return true;
	for(int i = head[x]; i != -1; i = e[i].next) {
		int to = e[i].to;
		if (to == pre) continue;
		if (Dfs(to, x, y)) {
			if (res > D[x]) res = D[x];
			return true;
		}
	}
	return false;
}

int main() {
	int n; read(n);
	memset(head, -1, sizeof(head));
	for(int i = 1; i < n; ++i) {
		int x, y, k; read(x); read(y); read(k);
		e[++tot]=edge(y,head[x],k),head[x]=tot; 
		e[++tot]=edge(x,head[y],k),head[y]=tot; 
	}
	int l, r; dfs(1, 0, l = 1); d[l] = 0; dfs(l, 0, r = l);
	dpl(l,0);memset(f1,0,sizeof(f1));memset(f2,0,sizeof(f2));dpr(r,0);
	Dfs(l, 0, r);  printf("%d\n", res);
	return 0;
} 
Published 10 original articles · won praise 6 · views 1486

Guess you like

Origin blog.csdn.net/Long_hen/article/details/105362217