zoukankan      html  css  js  c++  java
  • HDU6686 Rikka with Travels

    题意

    给一棵树,如果能选出两条没有交点的路径使得一条点数为x,一条点数为y,则(x,y)为合法对,求有多少合法对。
    题目链接

    思路

    其实我们需要求出对于每一个x其对应的最长的y,这样(x,1)....(x,y)都合法,也就是说x对答案贡献是y。因此我们讨论几种情况来更新每一个x的最大y。对于一棵树,可以分成一条直径和直径上每个点所连接的子树。这些子树有一些性质,第一子树根节点到最远的叶子节点的距离不大于子树根节点到直径两端较近一端的距离,否则直径会更长,第二子树的直径不大于直径,这个很显然。对于两条不相交的路径,第一种情况是在同一棵子树里,根据第二个性质,这种情况更新的答案不会优于选直径和除去直径后的直径,第二种情况是在不同的子树里,这种情况更新的答案不会优于选从直径两端不相交地走到两个根节点再分别在两个子树里走到离根节点最远的叶子结点。这个题太强了,我看了好几遍题解才明白。代码实现地也挺复杂。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int maxn = 100000+10;
    
    int n;
    int pre[2*maxn],other[2*maxn];
    int last[maxn],d[maxn],fr[maxn],len[maxn],mx[maxn],X[maxn],Y[maxn];
    bool vis[maxn];
    int tot;
    
    void add(int x,int y)
    {
        tot++;
        pre[tot]=last[x];
        last[x]=tot;
        other[tot]=y;
    }
    
    int bfs(int S)
    {
        queue<int> que;
        que.push(S);
        for (int i=1;i<=n;i++) d[i]=fr[i]=0;
        d[S]=1;
        while (!que.empty())
        {
            int x=que.front();
            que.pop();
            for (int p=last[x];p;p=pre[p])
            {
                int q=other[p];
                if (!d[q])
                {
                    d[q]=d[x]+1;
                    fr[q]=x;
                    que.push(q);
                }
            }
        }
        int T=S;
        for (int i=1;i<=n;i++)
        {
            if (d[i]>=d[T]) T=i;
        }
        return T;
    }
    
    int bfs1(int S,bool tag)
    {
        queue<int> que;
        stack<int> sta;
        que.push(S);
        sta.push(S);
        d[S]=1;
        vis[S]=tag;
        while (!que.empty())
        {
            int x=que.front();
            que.pop();
            for (int p=last[x];p;p=pre[p])
            {
                int q=other[p];
                if (!d[q]&&!vis[q])
                {
                    d[q]=d[x]+1;
                    vis[q]=tag;
                    que.push(q);
                    sta.push(q);
                }
            }
        }
        int T=S,D=1;
        while (!sta.empty())
        {
            if (d[sta.top()]>=D) T=sta.top(),D=d[T];
            d[sta.top()]=0;
            sta.pop();
        }
        if (tag) return D;
        return T;
    }
    
    int dfs(int x,int fa)
    {
        int ans=0;
        for (int p=last[x];p;p=pre[p])
        {
            int q=other[p];
            if (q!=fa&&!vis[q])
            {
                ans=max(ans,dfs(q,x));
            }
        }
        return ans+1;
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while (T--)
        {
            scanf("%d",&n);
            for (int i=1;i<=n;i++) last[i]=len[i]=mx[i]=0,vis[i]=0;
            tot=0;
            for (int i=1;i<n;i++)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                add(x,y);
                add(y,x);
            }
            int P=bfs(1);
            int Q=bfs(P);
            vector<int> li;
            int tmp=Q;
            while (tmp)
            {
                li.push_back(tmp);
                vis[tmp]=1;
                tmp=fr[tmp];
            }
            for (int i=0;i<li.size();i++) len[li[i]]=dfs(li[i],0);
            for (int i=0;i<=n+1;i++) X[i]=Y[i]=0;
            for (int i=0;i<li.size();i++)
            {
                X[i]=i+len[li[i]];
                Y[i]=li.size()-i-1+len[li[i]];
            }
            for (int i=1;i<li.size();i++) X[i]=max(X[i],X[i-1]);
            for (int i=li.size()-2;i>=0;i--) Y[i]=max(Y[i],Y[i+1]);
            for (int i=1;i<li.size();i++)
            {
                mx[X[i-1]]=max(mx[X[i-1]],Y[i]);
                mx[Y[i]]=max(mx[Y[i]],X[i-1]);
            }
            for (int i=1;i<=n;i++) d[i]=0;
            for (int i=1;i<=n;i++)
            {
                if (!vis[i])
                {
                    int P1=bfs1(i,0);
                    int Q1=bfs1(P1,1);
                    mx[li.size()]=max(mx[li.size()],Q1);
                    mx[Q1]=li.size();
                }
            }
            LL ans=0;
            for (int i=li.size()-1;i>=1;i--) mx[i]=max(mx[i],mx[i+1]);
            for (int i=li.size();i>=1;i--) ans+=mx[i];
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    sklearn 的 metrics
    转载:spring boot 中使用 jpa以及jpa介绍
    springboot 事件监听(@EventListener实现)
    多线程:创建线程和线程的常用方法
    缓存穿透、缓存击穿、缓存雪崩区别和解决方案
    不定义新变量,交换两个变量的值
    理解WebSocket心跳及重连机制
    SpringBoot实现WebSocket
    批量打包成ZIP压缩文件
    RocketMQ入门教程
  • 原文地址:https://www.cnblogs.com/zhanggengchen/p/11406181.html
Copyright © 2011-2022 走看看