codeforces 14D 树的直径

来源:互联网 发布:程序员薪资 编辑:程序博客网 时间:2024/05/21 22:33

题目大意:给你一棵树,要进行两次访问,两次访问中不能重复访问任一节点和边,问两次访问的最大长度乘积,每边 长度为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 longconst 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;}/*1513 1410 145 1010 69 1010 715 68 72 61 103 13 114 314 12*/


0 0
原创粉丝点击