21.10.17模拟 联络网 UVA11695弱化版

给一棵树,求修改一条边后的最小树的直径

考虑去掉一条边,形成两个子树,这两个子树怎么连边呢,肯定是子树的半径了
新的树的直径要么是两颗子树的直径的max,要么就是新边两个端点在所在子树为起点最长链的和+1,显然这个为起点最长链最小为子树的半径

考场只会n^2暴力。但是这题是远古题,可以过,luogu有个线性的,但是看不懂,待补

//uva11695
#include<bits/stdc++.h>
#define rep(i,j,k) for(int i(j);i<=k;++i)
#define drp(i,j,k) for(int i(j);i>=k;--i)
#define repg(x) for(int i(G.head[x]);i;i=G.next[i])
#define bug cout<<"~~~~~~~~~~~~~"<<'
';
using std::cin;
using std::cout;
typedef long long lxl;
template<typename T>
inline T  max( T a, T b) {
	return a > b ? a : b;
}
template<typename T>
inline T  min( T a, T b) {
	return a < b ? a : b;
}

inline char gt() {
	static char buf[1 << 21], *p1 = buf, *p2 = buf;
	return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++;
}
template <typename T>
inline void  read(T &x) {
	register char ch = gt();
	x = 0;
	int w(0);
	while(!(ch >= '0' && ch <= '9'))w |= ch == '-', ch = gt();
	while(ch >= '0' && ch <= '9')x = x * 10 + (ch & 15), ch = gt();
	w ? x = ~(x - 1) : x;
}
template <typename T>
inline void out(T x, char cc) {
	if(x < 0) x = -x, putchar('-');
	char ch[20];
	int num(0);
	while(x || !num) ch[++num] = x % 10 + '0', x /= 10;
	while(num) putchar(ch[num--]);
	putchar(cc);
}
const int N = 3e3 + 79;
int a[N], b[N];
struct graph {
	int head[N], tot, next[N << 1], ver[N << 1];
	inline void add(int a, int b) {
		ver[++tot] = b;
		next[tot] = head[a];
		head[a] = tot;
	}
} G;

int el, er, farest;
int dis[N], pre[N];
std::vector<int> GG;
std::queue<int> q;
inline void bfs(int st) {
	memset(dis, 0xff, sizeof dis);
	pre[st] = -1;
	dis[st] = 0;
	q.push(st);
	farest = st;
	while(!q.empty()) {
		int x = q.front();
		q.pop();
		repg(x) {
			int y(G.ver[i]);
			if(dis[y] != -1 || (min(x, y) == min(el, er) && max(x, y) == max(el, er)))continue;
			dis[y] = dis[x] + 1;
			pre[y] = x;
			q.push(y);
			if(dis[y] > dis[farest]) farest = y;
		}
	}
	GG.clear();
	int tmp = farest;
	while(tmp != -1) {
		GG.push_back(tmp);
		tmp = pre[tmp];
	}
}
int ans(1e9);
inline void solve() {
	int t(1);
	bfs(el);
	bfs(farest);
	t += (dis[farest] + 1) / 2;

	int aa = dis[farest];

	bfs(er);
	bfs(farest);
	t += (dis[farest] + 1) / 2;

	ans = min(ans, max(aa, max(t, dis[farest])));
}

int n;
int main() {
	freopen("network.in","r",stdin);
	freopen("network.out","w",stdout);
	read(n);
	rep(i, 1, n - 1) {
		read(a[i]);
		read(b[i]);
		G.add(a[i], b[i]);
		G.add(b[i], a[i]);
	}
	rep(i, 1, n - 1) {
		el = a[i];
		er = b[i];
		solve();
	}
	out(ans, '
');
	return 0;
}

本文来自博客园,作者:{2519},转载请注明原文链接:https://www.cnblogs.com/QQ2519/p/15419261.html

原文地址:https://www.cnblogs.com/QQ2519/p/15419261.html