codeforces 14D 树的直径

题目大意:给你一棵树,要进行两次访问,两次访问中不能重复访问任一节点和边,问两次访问的最大长度乘积,每边 长度为1

思路:因为n只有200,所以可以枚举从哪里将树分成两棵树即删除一条边,求两棵树的直径,维护乘积最大值即可。树的直径在以前的博文讲过,两遍dfs即可

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <iomanip>

using namespace std;
//#pragma comment(linker, "/STACK:102400000,102400000")
#define maxn 205
#define MOD 1000000007
#define mem(a , b) memset(a , b , sizeof(a))
#define LL long long
#define ULL long long
const long long INF=0x3fffffff;
int a[maxn][maxn];
int vis[maxn] , n , maxx , ed;
struct node
{
    int u , v;
}edge[maxn];

void dfs(int u , int dis)
{
    vis[u] = 1;
    if(maxx <= dis)
    {
        maxx = dis;
        ed = u;
    }
    for(int i = 1 ; i <= n ; i ++ )
    {
        if(a[u][i] && !vis[i])
            dfs(i , dis + 1);
    }
}

int main()
{
    while(scanf("%d" , &n) != EOF)
    {
        int pos = 2 , u , v ;
        mem(a , 0);
        mem(vis , 0);
        for(int i = 2 ;i <= n ; i ++)
        {
            scanf("%d %d" , &u , &v);
            edge[pos].u = u;
            edge[pos++].v = v;
            a[u][v] = a[v][u] = 1;
        }
        int res = 0 , len1 , len2;
        for(int i = 2 ; i <= n ; i ++)
        {
            u = edge[i].u;
            v = edge[i].v;
            a[u][v] = a[v][u] = 0;
            mem(vis , 0);
            ed = -1 , maxx = 0;
            dfs(u , 0);
            mem(vis , 0);
            maxx = 0;
           // if(ed != -1)
            dfs(ed , 0);
            len1 = maxx;

            mem(vis , 0);
            ed = -1 , maxx = 0;
            dfs(v , 0);
            mem(vis , 0);
            maxx = 0;
          //  if(ed != -1)
            dfs(ed , 0);
            len2 = maxx;
            res = max(res , len1 * len2);
            a[u][v] = a[v][u] = 1;
        }
        printf("%d\n" , res);
    }
    return 0;
}

/*
15
13 14
10 14
5 10
10 6
9 10
10 7
15 6
8 7
2 6
1 10
3 1
3 11
4 3
14 12

*/
时间: 2024-11-08 21:01:14

codeforces 14D 树的直径的相关文章

CodeForces 14D 树的直径 Two Paths

给出一棵树,找出两条不相交即没有公共点的路径,使得两个路径的长度的乘积最大. 思路:枚举树中的边,将该边去掉,分成两棵树,分别求出这两棵树的直径,乘起来维护一个最大值即可. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 7 const int maxn = 200 + 10; 8 9

CodeForces 379F 树的直径 New Year Tree

题意:每次操作新加两个叶子节点,每次操作完以后询问树的直径. 维护树的直径的两个端点U,V,每次计算一下新加进来的叶子节点到U,V两点的距离,如果有更长的就更新. 因为根据树的直径的求法,若出现新的直径,一定是到U或者到V距离最远. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 6 const int maxn = 1000000

Codeforces 14D Two Paths 树的直径

题目链接:点击打开链接 题意:给定一棵树 找2条点不重复的路径,使得两路径的长度乘积最大 思路: 1.为了保证点不重复,在图中删去一条边,枚举这条删边 2.这样得到了2个树,在各自的树中找最长链,即树的直径,然后相乘即可 #include<stdio.h> #include<iostream> #include<string.h> #include<set> #include<vector> #include<map> #includ

codeforces GYM 100114 J. Computer Network 无相图缩点+树的直径

题目链接: http://codeforces.com/gym/100114 Description The computer network of “Plunder & Flee Inc.” consists of n servers and m two-way communication links. Two servers can communicate either through a direct link, or through a chain of links, by relayi

codeforces 455C C. Civilization(树形dp+树的直径+并查集)

题目链接: codeforces 455C 题目大意: 给出一些点,他们之间初始存在一些边,给出两种操作,第一种是查询某个点所在的树的直径,另一种是将两个树合并,要求使合并后的树的直径最小. 题目分析: 首先算取没做操作前的连通块里的树的直径,也就是先dfs一遍,找到深度最大的点,然后从这个点再搜,找到的最远的距离就是这棵树的直径,因为可以证明从根搜深度最大的点一定是树的直径的一个端点,因为它可以通过到达次大的深度的点或者找到与它公共祖先不在根处的获得树的直径. 然后每次合并,我们可以知道得到的

codeforces GYM 100114 J. Computer Network tarjan 树的直径 缩点

J. Computer Network Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Description The computer network of “Plunder & Flee Inc.” consists of n servers and m two-way communication links. Two servers can communicate either thr

Codeforces 455C Civilization:树的直径 + 并查集【合并树后直径最小】

题目链接:http://codeforces.com/problemset/problem/455/C 题意: 给你一个森林,n个点,m条边. 然后有t个操作.共有两种操作: (1)1 x: 输出节点x所在树的直径. (2)2 x y: 如果x,y不在同一棵树上的话,用一条边连接x,y所在的树,并且使得到的新树的直径尽可能小. 题解: 首先对于初始状态,算出每一棵树的直径d[find(i)]. 每次合并树的时候,因为要尽可能让新树直径变小,所以显然这条边要分别连接两棵树直径的“中点”. 所以新树

Codeforces 455C Civilization 树的直径+并查集

题目链接:点击打开链接 题意: 给定n个点 m条无向边的图 k个询问 无重边.自环.环 定义 2个点属于同国家:当这两个点连通时即这两个点是属于一个国家 操作1 x:输出x所在的国家内的最长路长度 操作2 x y:若x y属于一个国家 则忽略 若不属于一个国家,则联合这两个国家(2个集合间连一条边.使得连完后最长路最短) 连2个集合的最长路一定是 找2个集合最长路的中点进行连接 则连接后的最长路长度为 path[x]/2 + path[y]/2 +1 (除2向上取整) 然后给每棵树预处理出树的直

树的直径 Codeforces Beta Round #14 (Div. 2) D. Two Paths

tiyi:给你n个节点和n-1条边(无环),求在这个图中找到 两条路径,两路径不相交,求能找的两条路径的长度的乘积最大值: #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <queue> #include <stack>