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;
} 

 

posted @ 2019-09-17 23:22  宿星  阅读(162)  评论(0编辑  收藏  举报