题目传送门

分析:

这什么奇奇怪怪的OJ,以前从来不知道的2333

以前只知道合并两个连通块时,其中一边直径端点为A,B,另一边为C,D

D=max( dis(A,B) , dis(A,C) , dis(A,D) , dis(B,C) , dis(B,D) , dis(C,D) )

原来合并两颗就在原树上可能交叉的虚树,竟然也可以用这个

而且多条直径也不会影响答案??

细想一下貌似很有道理的亚子。。。

记录记录2333

调了半天

这个歪歪扣不仅丧病而且脑子不太好使,虚树上两点之间连边距离不是1

太菜了dbq

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<iostream>
#include<map>
#include<string>

#define maxn 500005
#define INF 0x3f3f3f3f

using namespace std;

inline long long getint()
{
    long long num=0,flag=1;char c;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
    return num*flag;
}

int n,m,N;
int fir[maxn],nxt[maxn],to[maxn],cnt;
int fa[maxn],dpt[maxn],tp[maxn],sz[maxn],son[maxn];
int In[maxn],Out[maxn],cur;
int stk[maxn],top;
int Id[maxn];
int h[maxn],f[maxn];
vector<int>H[maxn];
int Rt[maxn][2];
map<string,int>M;
vector<int>G[maxn];
inline bool cmp(int x,int y){return In[x]<In[y];}

inline void newnode(int u,int v)
{to[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;}

inline void dfs1(int u)
{
    sz[u]=1;
    for(int i=fir[u];i;i=nxt[i])
        if(to[i]!=fa[u])
        {
            dpt[to[i]]=dpt[u]+1,fa[to[i]]=u;
            dfs1(to[i]);
            sz[u]+=sz[to[i]];if(sz[to[i]]>sz[son[u]])son[u]=to[i];
        }
}

inline void dfs2(int u,int ac)
{
    In[u]=++cur,tp[u]=ac;
    if(son[u])dfs2(son[u],ac);
    for(int i=fir[u];i;i=nxt[i])if(to[i]!=fa[u]&&to[i]!=son[u])dfs2(to[i],to[i]);
    Out[u]=cur;
}

inline int LCA(int u,int v)
{
    while(tp[u]!=tp[v])
    {
        if(dpt[tp[u]]<dpt[tp[v]])swap(u,v);
        u=fa[tp[u]];
    }
    return dpt[u]<dpt[v]?u:v;
}

inline void getdp(int u,int lst)
{
    for(int i=G[u].size()-1;~i;i--)if(G[u][i]!=lst)
        f[G[u][i]]=f[u]+abs(dpt[u]-dpt[G[u][i]]),getdp(G[u][i],u);
}

inline void solve(int x)
{
    int K=H[x].size();top=0;
    for(int i=0;i<K;i++)h[i+1]=H[x][i];
    sort(h+1,h+K+1,cmp);
    for(int i=K-1;i;i--)h[++K]=LCA(h[i],h[i+1]);
    sort(h+1,h+K+1,cmp);K=unique(h+1,h+K+1)-h-1;
    stk[++top]=h[1];
    for(int i=2;i<=K;i++)
    {
        while(top&&Out[stk[top]]<In[h[i]])top--;
        if(top)G[stk[top]].push_back(h[i]),G[h[i]].push_back(stk[top]);
        stk[++top]=h[i];
    }
    int rt=h[1];
    f[rt]=0;getdp(rt,rt);
    for(int i=1;i<=K;i++)if(f[h[i]]>f[rt])rt=h[i];
    Rt[x][0]=rt;
    f[rt]=0;getdp(rt,rt);
    for(int i=1;i<=K;i++)if(f[h[i]]>f[rt])rt=h[i];
    Rt[x][1]=rt;
    for(int i=1;i<=K;i++)G[h[i]].clear();
}

inline int getdis(int u,int v)
{return dpt[u]+dpt[v]-2*dpt[LCA(u,v)];}

inline int getans(int x,int y)
{
    int A=Rt[x][0],B=Rt[x][1],C=Rt[y][0],D=Rt[y][1];
    return max(max(getdis(A,C),getdis(A,D)),max(getdis(B,C),getdis(B,D)));
}

int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        M.clear();
        memset(fir,0,sizeof fir),cnt=0;
        memset(son,0,sizeof son);cur=0;
        memset(fa,0,sizeof fa),memset(sz,0,sizeof sz);
        memset(tp,0,sizeof tp),memset(dpt,0,sizeof dpt);
        memset(Rt,0,sizeof Rt);memset(Id,0,sizeof Id);
        memset(In,0,sizeof In),memset(Out,0,sizeof Out);
        for(int i=1;i<=n;i++)
        {
            string tmp;cin>>tmp;
            if(!M.count(tmp))M[tmp]=++N;
            Id[i]=M[tmp];
            H[M[tmp]].push_back(i);
        }
        for(int i=1;i<n;i++)
        {
            int u=getint(),v=getint();
            newnode(u,v),newnode(v,u);
        }
        dfs1(1),dfs2(1,1);
        for(int i=1;i<=N;i++)solve(i);
        while(m--)
        {
            string tmp1,tmp2;
            cin>>tmp1>>tmp2;
            if(!M.count(tmp1)||!M.count(tmp2))printf("-1\n");
            else printf("%d\n",getans(M[tmp1],M[tmp2])+1);
        }
        for(int i=1;i<=N;i++)H[i].clear();N=0;
    }
}
View Code
12-21 23:27