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