知识点:贪心,树的遍历
难度:5
我真的是操了,这已经不知道是多少次因为无向边而把数组开小导致一直卡着,这个题的题意就是有若干棵无根树,问把这些树拼接起来最长的直径能有多少,总体的思路就是对于每个无根树,我们都让他们贡献出最长的直径,这样拼接起来得到的树一定直径最长,题解里面说了还好是最长,那么这样是比较简单的,这样贪心即可,看来如果是最短那么会更难一点,
然后就是子操作,如何求一个无根树的最长的直径,看题解里面说了有两种方法,一种是两遍的dfs或bfs,一种是树形dp,那么我现在肯定只能用搜索来做,具体的方法就是我们先任取一个点,求出以他为根的最深的节点,然后再以那个最深的节点为根再进行一次dfs,这样第二次求出来的最深的深度就是这个无根树的最长的直径,第一次接触无根树的概念,不是很熟悉,无根树虽然边的数目也是顶点数减一,但是边是无向的,所以我们涉及到边的数组要开成原来的2倍,
一开始想的暴力求无根树直径做法超时了,也是很不懂为啥会超时,
- #include
-
- using namespace std;
-
- const int N = 105;
-
- int tot, ver[N * 2], nxt[N * 2], head[N];
- int n, vis[N], dep[N], dmax, root;
-
- void add(int x, int y) {
- ver[++tot] = y;
- nxt[tot] = head[x]; head[x] = tot;
- }
-
- void dfs(int v) {
- vis[v] = 1;
- for (int i = head[v]; i; i = nxt[i]) {
- int y = ver[i];
- if (vis[y]) continue;
- dep[y] = dep[v] + 1;
- if (dep[y] > dmax) {
- dmax = dep[y];
- root = y;
- }
- dfs(y);
- }
- }
-
- int main() {
- freopen("input.txt","r",stdin);
- freopen("output.txt","w",stdout);
- int T;
- cin >> T;
- int ans = 0;
- while (T--) {
- tot = 0;
- memset(head, 0, sizeof(head));
- memset(vis, 0, sizeof(vis));
- memset(dep, 0, sizeof(dep));
- dmax = -1;
- cin >> n;
- for (int i = 1; i <= n - 1; i++) {
- int x, y;
- cin >> x >> y;
- add(x, y);
- add(y, x);
- }
- dfs(1);
- memset(vis, 0, sizeof(vis));
- memset(dep, 0, sizeof(dep));
- dmax = -1;
- dfs(root);
- ans += dmax;
- }
- cout << ans;
- return 0;
- }