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

 

posted @ 2014-07-30 11:17  默默无语敲代码  阅读(932)  评论(0编辑  收藏  举报