列表

详情


NC229068. 孤独

描述

对着相遇的幻景挥手作别
憧憬着这片天空
手心里流逝的岁月
像一朵孤独的花瓣一样
重复着疼痛,知道了相遇
——《茜さす》
人之间的联系何尝又不是一棵树,一条条边割断后便有了孤独……
给定一棵树,寻找一个路径,将断掉所有与这个路径上的点相连的边,使得剩下的最大连通块的大小最小(可以根据样例解释进行理解)

输入描述

一行一个整数n,表示节点个数(节点编号从1开始)
接下来n−1行,每行两个整数,表示一条边x,y

输出描述

一行表示最小情况下,最大连通块的大小。

示例1

输入:

10
2 1
3 2
4 1
5 2
6 5
7 4
8 6
9 7
10 3

输出:

2

说明:

由图,剩余的最大连通块为{3,10},大小为2

示例2

输入:

2
1 2

输出:

1

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 934ms, 内存消耗: 77356K, 提交时间: 2022-12-20 16:04:44

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int ans = INT_MAX, n;
int sz[1000006];
int dp[1000006];
vector<int>vec[1000006];
void dfs(int i, int fa) {
	sz[i] = 1;
	int mx1 = 0;
	int mx2 = 0;
	int mx3 = 0; //第三大的子树
	for (auto j : vec[i]) {
		if (j == fa)continue;
		dfs(j, i);
		sz[i] += sz[j];
		if (sz[j] > sz[mx1]) {
			mx3 = mx2;
			mx2 = mx1;
			mx1 = j;
		} else if (sz[j] > sz[mx2]) {
			mx3 = mx2;
			mx2 = j;
		} else if (sz[j] > sz[mx3]) {
			mx3 = j;
		}
		dp[i] = max(dp[mx1], sz[mx2]);
	}
	ans = min(ans, max(n - sz[i], max(dp[mx1], max(dp[mx2], sz[mx3]))));
}
int main() {
	int i, j, x, y;
	scanf("%d", &n);
	for (i = 1; i < n; i++) {
		scanf("%d%d", &x, &y);
		vec[x].push_back(y);
		vec[y].push_back(x);
	}
	dfs(1, 0);
	printf("%d\n", ans);
	return 0;
}

C++ 解法, 执行用时: 696ms, 内存消耗: 64180K, 提交时间: 2021-10-24 15:40:13

#include <bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int n,sz[N],sig[N];
vector<int> g[N];
int res=2e9;
void dfs(int u,int fa){
	int mx=0,se=0,th=0;
	sz[u]=1;
	for(auto y:g[u]){
		if(y==fa) continue;
		dfs(y,u);
		sz[u]+=sz[y];
		if(sz[y]>=sz[mx]) {
			th=se;se=mx;mx=y;
		}else if(sz[y]>=sz[se]) {
			th=se;se=y;
		}else if(sz[y]>=sz[th]) th=y;
	}
	sig[u]=max(sig[mx],sz[se]);
	res=min(res,max({sz[th],sig[mx],sig[se],n-sz[u]}));
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<n;i++){
		int x,y;scanf("%d %d",&x,&y);
		g[x].push_back(y);
		g[y].push_back(x);
	}
	dfs(1,0);
	res=max(res,1);
	cout<<res<<'\n';
}

上一题