把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

Two Paths CodeForces - 14D【dfs 树的直径】

传送门

分析

刚开始的时候想的是求最长路和次长路,没有注意到题目中的条件是要求2条路不能交叉(2条路不能有公共的城市)。于是乎,就枚举边,把边删掉,然后在每个块里面求最长路。

刚开始想用spfa,把每条边的边权取反,求最短路,然后打着打着发现这么要枚举s,t,正解应该打树的直径(n个城市,n-1条边,联通,删去一条边之后就是2棵树)

写图论习惯了vector邻接表,然而这道题数据范围只有200,可以写邻接矩阵在“删边”的时候更方便。

//求2条不相交的最长路
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define MAXN 205
#define INF 0x3f3f3f3f
#define LL long long
vector<pair<int,int> > G[MAXN];
int n,ans;
int d[MAXN];
bool vis[MAXN];
bool mark[MAXN][MAXN];
void dfs(int u,int x,int y)
{
	vis[u]=1;
	for(int i=0;i<G[u].size();i++)
	{
		int v=G[u][i].first,w=G[u][i].second;
		if((u==x&&v==y)||(u==y&&v==x)) continue;
		if(!vis[v])
		{
			d[v]=d[u]+w;//一个节点最多更新一次,放在vis判断里面防止重复更新父节点
			dfs(v,x,y);
		}
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<n;i++)
	{
		int u,v;
		scanf("%d %d",&u,&v);
		G[u].push_back(make_pair(v,1));
		G[v].push_back(make_pair(u,1));
	}
	for(int i=1;i<=n;i++)
		for(int j=0;j<G[i].size();j++)
		{
			int v=G[i][j].first,ans1=0,ans2=0,mx=0,s=i;
			if(mark[i][v]) continue;
			mark[v][i]=1;
			
			memset(d,0,sizeof(d));
			memset(vis,0,sizeof(vis));
			dfs(i,i,v);
			for(int k=1;k<=n;k++)
				if(d[k]>mx) mx=d[k],s=k;
			memset(d,0,sizeof(d));
			memset(vis,0,sizeof(vis));
			dfs(s,i,v);
			for(int k=1;k<=n;k++)
				if(d[k]>ans1) ans1=d[k];
			
			memset(d,0,sizeof(d));
			memset(vis,0,sizeof(vis));
			dfs(v,i,v);
			s=v,mx=0;
			for(int k=1;k<=n;k++)
				if(d[k]>mx) mx=d[k],s=k;
			memset(d,0,sizeof(d));
			memset(vis,0,sizeof(vis));
			dfs(s,i,v);
			for(int k=1;k<=n;k++)
				if(d[k]>ans2) ans2=d[k];
					
			if(ans1*ans2>ans) ans=ans1*ans2;
		}
	printf("%d\n",ans);
	return 0;
}
posted @ 2018-08-08 18:02  Starlight_Glimmer  阅读(9)  评论(0编辑  收藏  举报  来源
浏览器标题切换
浏览器标题切换end