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;
}
转载请注明出处,有疑问欢迎探讨
博主邮箱 2775182058@qq.com