Codeforces Beta Round #14 (Div. 2) D. Two Paths
来源:互联网 发布:知联会是什么组织 编辑:程序博客网 时间:2024/05/29 20:05
题目链接
题目大意
给定一棵无向树。从中选择两条不相交的路径,使得两条路径的长度乘积最大。
路径不相交定义为两个路径没有公共点。
题解
首先可以想到一个O(n^4)的算法,就是枚举4个点,也就是两条路径,然后判断是否可行。
考虑如何优化,可以先用n^2的复杂度枚举一条路径,然后贪心得去求另一条路径,另一条路径当然越大越好了。
而从树中删掉一条路径,剩下的就是森林了,在每棵树上求一下直径,求出最大值,就可以更新答案了。
这题的数据范围是n<=200,所以O(n^3)足以过掉这道题了。
#include<cstdio>#include<algorithm>using namespace std;const int M=205;struct Edge{ int to,nxt;}edge[M<<1];int T,head[M];void add_edge(int a,int b){ edge[T]=(Edge){b,head[a]}; head[a]=T++;}int fa[M],dep[M];int mx,ID,ans,n;bool mark[M],flag[M];void rec(int x,int f,int d){ if(!dep[x]) fa[x]=f,dep[x]=d; mark[x]=1; if(mx<d){ mx=d; ID=x; } for(int i=head[x];~i;i=edge[i].nxt){ if(flag[edge[i].to]||edge[i].to==f) continue; rec(edge[i].to,x,d+1); }}int LCA(int a,int b){ if(dep[a]<dep[b]) swap(a,b); while(dep[a]>dep[b]) flag[a]=1,a=fa[a]; while(a!=b){ flag[a]=1; flag[b]=1; a=fa[a],b=fa[b]; } flag[a]=flag[b]=1; return a;}void solve(int a,int b){ for(int i=1;i<=n;i++) flag[i]=mark[i]=0; int lca=LCA(a,b),l=0; for(int i=1;i<=n;i++) if(!mark[i]){ mx=-1;rec(i,0,0); mx=-1;rec(ID,0,0); l=max(l,mx); } ans=max(ans,l*(dep[a]+dep[b]-dep[lca]*2));}int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) head[i]=-1; for(int i=1;i<n;i++){ int a,b; scanf("%d%d",&a,&b); add_edge(a,b); add_edge(b,a); } rec(1,0,1); for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) solve(i,j); printf("%d\n",ans); return 0;}
然而这还不算完,还有O(n^2)的做法。
由于这棵树是联通的,所以选完了两条路径之后肯定存在第三条路径连接着两条路径。
于是枚举一条边,然后树就被分成了两棵树,求出两棵树的直径的最大值,然后就可以更新答案了。
#include<cstdio>#include<algorithm>using namespace std;const int M=205;struct Edge{ int to,nxt;}edge[M<<1];int head[M],T,del,len[2];void add_edge(int a,int b){ edge[T]=(Edge){b,head[a]}; head[a]=T++;}int mx,ID;void rec(int x,int f,int dep){ if(dep>mx){ mx=dep; ID=x; } for(int i=head[x];~i;i=edge[i].nxt){ if(edge[i].to==f||del==(i>>1)) continue; rec(edge[i].to,x,dep+1); }}void solve(int x,int f){ mx=-1; rec(x,0,0); rec(ID,0,0); len[f]=mx;}int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;i++) head[i]=-1; for(int i=1;i<n;i++){ int a,b; scanf("%d%d",&a,&b); add_edge(a,b); add_edge(b,a); } int ans=0; for(int i=0;i<n-1;i++){ del=i; solve(edge[i<<1].to,0); solve(edge[i<<1|1].to,1); ans=max(ans,len[0]*len[1]); } printf("%d\n",ans); return 0;}
思考
如果可以选择k条路径,那可以怎么写呢?
1 0
- Codeforces Beta Round #14 (Div. 2) D. Two Paths
- Codeforces Beta Round #14 D - Two Paths
- 【DFS——Codeforces Beta Round #14 (Div. 2)】D. Two Paths
- Codeforces Beta Round #14 (Div. 2) D. Two Paths 树形dp
- Codeforces Round #14 (Div. 2) D. Two Paths ( 树的直径
- Codeforces Round #351 (VK Cup 2016 Round 3, Div. 2 Edition) D. Bear and Two Paths
- Codeforces Round #351 (VK Cup 2016 Round 3, Div. 2 Edition) D. Bear and Two Paths
- 【Codeforces Beta Round #36】Codeforces 36E Two Paths
- Codeforces Beta Round #14 (Div. 2)
- 【KMP】Codeforces Beta Round #93 (Div. 2 Only) D
- Codeforces Beta Round #35 (Div. 2), problem: (D) Animals DP
- Codeforces Beta Round #75 (Div. 2 Only)——D
- Codeforces Beta Round #52 (Div. 2) D - Changing a String
- Codeforces Beta Round #95 (Div. 2) D.Subway
- Codeforces Beta Round #89 (Div. 2)D. Caesar's Legions
- Codeforces Beta Round #4 (Div. 2 Only)D. Mysterious Present
- Codeforces Beta Round #67 (Div. 2) D. Big Maximum Sum
- Codeforces Beta Round #18 (Div. 2 Only) D - Seller Bob
- OPENSTACK常见问题及注意事项汇总
- ReactJS学习系列课程(props 组件属性)
- ASP.NET MVC Bootstrap 个人博客站 www.zynblog.com
- 动画 方块旋转
- Codeforces Round #359 (Div. 2) 部分题解
- Codeforces Beta Round #14 (Div. 2) D. Two Paths
- spring mvc 传中文 到controller层乱码的 解决方法
- C++设计模式系列之二结构型模式
- Android Studio中获取sha1证书指纹
- svn服务器搭建流程
- Java 用两种方法实现插入排序
- phpcms制作静态手机移动站
- Servlet开发(四)Response对象、Request对象的请求重定向、请求转发
- Mac系统mds、mds_stores、mdworker疯狂工作的问题