1. 程式人生 > >【Atcoder - AGC001C】Shorten Diameter

【Atcoder - AGC001C】Shorten Diameter

@Shorten [email protected]


@Problem [email protected]

Given an undirected tree, let the distance between vertices u and v be the number of edges on the simple path from u to v. The diameter of a tree is the maximum among the distances between any two vertices. We will call a tree good if and only if its diameter is at most K.
You are given an undirected tree with N vertices numbered 1 through N. For each i(1≦i≦N−1), there is an edge connecting vertices Ai and Bi.
You want to remove zero or more vertices from the tree, so that the resulting tree is good. When a vertex is removed, all incident edges will also be removed. The resulting graph must be connected.
Find the minimum number of vertices that you need to remove in order to produce a good tree.

Constraints
2≦N≦2000
1≦K≦N−1
1≦Ai≦N,1≦Bi≦N
The graph defined by Ai and Bi is a tree.

Input
The input is given from Standard Input in the following format:
N K
A1 B1
A2 B2
:
AN−1 BN−1

Output
Print the minimum number of vertices that you need to remove in order to produce a good tree.

Sample Input 1


6 2
1 2
3 2
4 2
1 6
5 6
Sample Output 1
2
The tree is shown below. Removing vertices 5 and 6 will result in a good tree with the diameter of 2.
題目描述圖

Sample Input 2
6 5
1 2
3 2
4 2
1 6
5 6
Sample Output 2
0
Since the given tree is already good, you do not need to remove any vertex.

@[email protected]

給你一棵包含 N 個點的樹。N <= 2000。
進行若干次操作,每次操作刪除一個葉子。
求最少次的操作,使得剩下的樹的直徑 <= K。

@[email protected]

首先可以用反證法證明這樣一個結論:如果一棵樹有多條直徑,所有的直徑共中點(如果是長度為奇數則共中間一條邊)。
因此:我們可以列舉最後剩下的樹的中點,刪去深度 >= K/2 的結點統計答案。
總時間複雜度為O(n^2)。

注意分類討論直徑為奇數或偶數。

@[email protected]

思維題/結論題,利用了樹直徑的一些性質qwq。
這個部落格感覺好像有點兒摻水。。。

#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 2000;
struct edge{
	int to;
	edge *nxt;
}edges[MAXN*2 + 5], *adj[MAXN + 5], *ecnt = &edges[0];
void addedge(int u, int v) {
	edge *p = (++ecnt);
	p->to = v, p->nxt = adj[u], adj[u] = p;
	p = (++ecnt);
	p->to = u, p->nxt = adj[v], adj[v] = p;
}
queue<int>que;
int dis[MAXN + 5], vis[MAXN + 5], N, K;
int solve() {
	int ret = 0;
	while( !que.empty() ) {
		int f = que.front(); que.pop();
		if( dis[f] > K/2 ) ret++;
		for(edge *p=adj[f];p!=NULL;p=p->nxt) {
			if( !vis[p->to] ) {
				vis[p->to] = true;
				dis[p->to] = dis[f] + 1;
				que.push(p->to);
			}
		}
	}
	return ret;
}
int main() {
	scanf("%d%d", &N, &K);
	for(int i=1;i<N;i++) {
		int A, B;
		scanf("%d%d", &A, &B);
		addedge(A, B);
	}
	int ans = MAXN + 5;
	if( K % 2 == 0 ) {
		for(int i=1;i<=N;i++) {
			for(int j=1;j<=N;j++) {
				vis[j] = false;
				dis[j] = 0;
			}
			vis[i] = true; que.push(i);
			ans = min(ans, solve());
		}
	}
	else {
		for(int i=1;i<=N;i++) {
			for(edge *p=adj[i];p!=NULL;p=p->nxt) {
				if( i > p->to ) continue;
				for(int j=1;j<=N;j++) {
					vis[j] = false;
					dis[j] = 0;
				}
				vis[i] = true; que.push(i);
				vis[p->to] = true; que.push(p->to);
				ans = min(ans, solve());
			}
		}
	}
	printf("%d\n", ans);
}

@[email protected]

就是這樣,新的一天裡,也請多多關照哦(ノω<。)ノ))☆.。