51Nod 1694: 两条路径(图论)
Bob的哥哥住在法国。在法国有n个城市,有n-1条双向道路连通这些城市。这些城市从1~n编号。你能沿着这些道路从一个城市走到任意一个城市。
Bob的哥哥供职于“两条路”公司,并且刚好拿到了去修缮法国的任意两条路径的项目。一条路径指的是连通两个不同的城市的道路序列。公司能自主选择要修缮的道路,唯一的条件是这两条路径不能交叉(即不能有共同的城市)。
当然,我们都知道存在利润,“两条路”公司得到的利润将等于两条路径的长度的乘积。假设每条道路的长度等于1,并且路径的长度等于道路的数量。请你为这公司获得最大的利润。
输入
单组测试数据。
第一行是一个整数 n (2≤n≤200) ,n是这个国家的城市的数量。
接下来n-1行是道路的信息,每一行是两个整数ai,bi,它们是城市的编号,表示ai和bi之间有一条道路直接连通。(1≤ai,bi≤n)。
输出
输出最大的利润。
输入样例
4
1 2
2 3
3 4
输出样例
1
解题思路:
题目要求找到两条路径的长度乘积最大, 数据量较小,可以暴力去掉每一条边,把图分成两部分,再求两个图的深度相乘,取最大值。
#include <stdio.h>
#include <vector>
#include <queue>
#include <string.h>
#include <algorithm>
const int N = 220;
using namespace std;
struct edge {
int st;
int l;
edge (){}
edge (int st, int l):st(st), l(l){}
};
vector<int>e[N];
bool book[N];
int n;
int BFS(int v, int f)
{
queue<edge>q;
int s;
memset(book, false, sizeof(book));
q.push(edge(v, 0));
book[v]=book[0]=true;
int temp=0;
while (!q.empty()) {
edge &u=q.front();
q.pop();
s=u.st;
temp=max(temp, u.l);
for (int i=0; i<e[s].size(); i++) {
if(book[e[s][i]]==false) {
book[e[s][i]]=true;
q.push(edge(e[s][i], u.l+1));
}
}
}
if(f==1)
return s;
if(f==2)
return temp;
}
void init()
{
int u, v;
for (int i=0; i<=n; i++)
e[i].clear();
for (int i=1; i<n; i++) {
scanf("%d%d", &u, &v);
e[u].push_back(v);
e[v].push_back(u);
}
}
int cut(int u, int v)
{
int s=e[u][v];
int t;
e[u][v]=0;
for(int i=0; i<e[s].size(); i++)
if(e[s][i]==u) {
t=i;
e[s][i]=0;
break;
}
int start1=BFS(u, 1);
int sum1=BFS(start1, 2);
int start2=BFS(s, 1);
int sum2=BFS(start2, 2);
e[u][v]=s;
e[s][t]=u;
return sum1*sum2;
}
int main()
{
int ans;
while(scanf("%d", &n)!=EOF) {
init();
ans=0;
for(int i=1; i<=n; i++) {
for(int j=0; j<e[i].size(); j++)
ans=max(ans, cut(i, j));
}
printf("%d\n", ans);
}
return 0;
}