首页 > 代码库 > SPOJ TWOPATHS Two Paths
SPOJ TWOPATHS Two Paths
题目意思:给一棵树,找到俩个不相交的通路,使得这俩个通路的长度和乘机最大;
解法:
小哥一看呵呵 这不就是枚举点 然后求俩边的树的直径在相乘求个最大值的题么!
呵呵 这个N 有100000 当时就不玩了;
学长指导了下我;
俺会了!/灯泡
在枚举点在书的直径上时点的左右的最长的链无非这几种情况如图(红色是树得直径)(蓝色和绿色是俩种情况)
无非就 蓝色和绿色这个俩种,所以这个答案和直径有很大的关系!
不在直径上时:一边肯定是直径了另一半呢?如图;
解的过程:
1: 想求出直径的点顺序的 存在一个数组内;
2: 求出和每个直径上节点相邻的 最大和次大 和直径不相连的 链的 长度 并求出Max(这个链的点都不在直径上)
3:O(n)枚举点并求出这个点的左右的长度最值
4:由3的结果求出最大的ANS ,在和树得直径*Max取最值
over:
代码
#include <cstring>#include <algorithm>#include <cmath>#include <cstdio>#include <cstdlib>using namespace std;const int INF=0x7fffffff;const int maxn=100002;struct Edge{ int to,pre; Edge (int to=0,int pre=0):to(to),pre(pre){}};Edge edge[maxn*2];int head[maxn],pos;bool vis[maxn];bool in_line[maxn];int ko[maxn],pos_ko;int dp[maxn][2];int dp1[maxn],dp2[maxn];struct info{ int p,pre;};info que[maxn];void inint(){ memset(head,-1,sizeof(head)); pos=pos_ko=0; memset(dp,0,sizeof(dp)); memset(in_line,false,sizeof(in_line)); memset(dp1,0,sizeof(dp1)); memset(dp2,0,sizeof(dp2));}void add_edge(int s,int to){ edge[pos]=Edge(to,head[s]); head[s]=pos++;}void make(int P){ if(que[P].pre!=-1)make(que[P].pre); ko[pos_ko++]=que[P].p; in_line[que[P].p]=true;}int bfs(int t,bool flag){ memset(vis,false,sizeof(vis)); int h=0,r=1; que[0].p=t; que[0].pre=-1; vis[t]=true; int x; while(h<r) { x=que[h++].p; for(int i=head[x];~i;i=edge[i].pre) { Edge &tmp=edge[i]; if(!vis[tmp.to]) que[r].p=tmp.to, que[r++].pre=h-1, vis[tmp.to]=true; } } if(flag)make(r-1); return que[r-1].p;}void get_it(int key,int t){ if(key>dp[t][0])dp[t][1]=dp[t][0], dp[t][0]=key; else if(key>dp[t][1]) dp[t][1]=key;}int Max;int dfs(int pa,int &s,int &t){ int key,ans=0; for(int w=head[s];~w;w=edge[w].pre) { Edge &tmp=edge[w]; if(tmp.to==pa||in_line[tmp.to])continue; key=dfs(s,tmp.to,t); if(pa==-1) get_it(key,t); if(pa!=-1) { if(ans) Max=max(Max,ans-1+key); else Max=max(Max,key); } ans=max(ans,key+1); } if(pa==-1)Max=max(Max,ans-2); return ans==0?1:ans;}void solve(int &n){ long long ans=0; Max=0; int p1=bfs(1,false),p2=bfs(p1,true); int Max1; for(int i=0;i<pos_ko;i++) dfs(-1,ko[i],i); ans=(pos_ko-1)*Max; --pos_ko; for(int i=1;i<pos_ko;i++) { dp1[i]=max(dp1[i-1],i+dp[i][0]); dp1[i]=max(dp1[i],dp[i][0]+dp[i][1]); } for(int i=pos_ko-1;i>=0;i--) { dp2[i]=max(dp2[i+1],pos_ko-i+dp[i][0]); dp2[i]=max(dp2[i],dp[i][0]+dp[i][1]); } for(int i=1;i<pos_ko;i++) ans=max(ans,(long long)dp1[i]*dp2[i+1]); ans=max(ans,(long long )0); printf("%lld\n",ans);}int main(){ int n; int a,b; while(~scanf("%d",&n)) { inint(); for(int i=2;i<=n;i++) { scanf("%d%d",&a,&b); add_edge(a,b); add_edge(b,a); } solve(n); } return 0;}
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。