杂题(队列、找规律)
描述(A 输入文件 : A.input 输出文件 : A.output)
一个城市的构成是一颗n 个节点的树(2 ≤ n ≤ 200), 现在需要在树中找出两条不相交的路
径(即两条路径不能有重边也不能有重点),使得路径的长度的乘积最大。
输入描述
第一行一个数n 表示这个城市一共有 n 个节点。
接下来 n-1 行,每行两个数ai 和bi (1 ≤ ai,bi ≤ n ),分别表示从ai 到bi,有一条边,每条边
的长度为1。
输出描述
输出一行一个数表示两条路径长度最大的乘积。
样例数据
样例输入1:
7
1 2
1 3
1 4
1 5
1 6
1 7
样例输出1:
0
样例输入2:
6
1 2
2 3
2 4
5 4
6 4
样例输出2:
4
枚举边分成两棵树,分别求出两棵树的直径。找出所有情况的乘积最大值。求一棵树直径的方法:从任意一点dfs最远点设为i,再从i点dfs最远点,设为j,则i到j为直径。
#include<cstdio>
#include<cstring>
const int MAX_SIZE = 200;
int f[MAX_SIZE + 10][2], g[MAX_SIZE + 10], en;
int n, nodes[MAX_SIZE + 10], nxt[MAX_SIZE * 2 + 10], to[MAX_SIZE * 2 + 10];
int ans;
inline int max(int a, int b) { return a > b ? a : b; }
inline void addEdge(int f, int t)
{
++ en;
to[en] = t;
nxt[en] = nodes[f];
nodes[f] = en;
}
bool vis[MAX_SIZE + 10];
void dfs(int cur, int fa)
{
f[cur][0] = f[cur][1] = 0;
g[cur] = 0;
for(int e = nodes[cur]; e; e = nxt[e])
{
if(to[e] == fa)
continue;
dfs(to[e], cur);
g[cur] = max(g[cur], g[to[e]]);
if(f[to[e]][0] + 1 > f[cur][0])
{
f[cur][1] = f[cur][0];
f[cur][0] = f[to[e]][0] + 1;
} else if(f[to[e]][0] + 1 > f[cur][1])
f[cur][1] = f[to[e]][0] + 1;
g[cur] = max(g[cur], f[cur][0] + f[cur][1]);
}
}
int calcMax()
{
int maxn = 0;
for(int i = 1; i <= n; i ++)
{
if(vis[i])
{
int cur = i;
for(int e = nodes[cur]; e; e = nxt[e])
if(!vis[to[e]])
{
dfs(to[e], cur);
if(g[to[e]] > maxn)
maxn = g[to[e]];
}
}
}
return maxn;
}
void dfsAns(int cur, int len)
{
vis[cur] = true;
ans = max(len * calcMax(), ans);
for(int e = nodes[cur]; e; e = nxt[e])
if(!vis[to[e]])
dfsAns(to[e], len + 1);
vis[cur] = false;
}
int main()
{
freopen("A.input", "r", stdin);
freopen("A.output", "w", stdout);
scanf("%d", &n);
for(int i = 1; i < n; i ++)
{
int a, b;
scanf("%d%d", &a, &b);
addEdge(a, b);
addEdge(b, a);
}
for(int i = 1; i <= n; i ++)
dfsAns(i, 0);
printf("%d\n", ans);
return 0;
}
另外,有一种