• hdu 4008 树形dp


    思路:我们定义一个dfn[i],Maxndfn[i]来确定节点i的访问次序,以及其子节点的最大访问次序。那么另一个节点是其子树的节点当且仅当dfn[j]>=dfn[i]&&dfn[j]<=Maxdfn[i];

    这是就可以先以1为根,dfs找出所有节点最小儿子,次小儿子,以及最小子孙,次小子孙。

    剩下就可以分情况:

    对于x,y:

    1.若与y相连的边数为1,那么一定就是no answers!。

    2.对于最小儿子节点的询问:

    (1)若x是y的子节点,那么如果x包含在y的最小儿子子树中,那么就答案就是次小儿子与其父节点中较小的,否则就是最小儿子与其父节点中较小的。

    (2)若y是x点子节点(设不是y的子节点的都是其根节点),那么就直接输出最小儿子。

    3.对于最小子孙节点的询问:

    (1)若x是y的子节点,那么如果x包含在y的最小子孙所在子树中(小于以y为根的子树),那么就答案就是次小子孙,否则就是最小子孙,其实这只设和y为1的情况,若y为其它节点,其最小子孙直接就是1。

    (2)若y是x点子节点(设不是y的子节点的都是其根节点),那么就直接输出最小子孙。

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    #include<queue>
    #define Maxn 100010
    #define inf 0x7fffffff
    using namespace std;
    int son[Maxn],nson[Maxn],der[Maxn],nder[Maxn],n,q,dfn[Maxn],Maxdfn[Maxn],lab,dp[Maxn],road[Maxn],father[Maxn];
    vector<int> head[Maxn];
    void init()
    {
        int i;
        memset(son,0,sizeof(son));
        memset(nson,0,sizeof(nson));
        memset(der,0,sizeof(der));
        memset(nder,0,sizeof(nder));
        memset(dfn,0,sizeof(dfn));
        memset(father,0,sizeof(father));
        memset(dp,0,sizeof(dp));
        memset(road,0,sizeof(road));
        memset(Maxdfn,0,sizeof(Maxdfn));
        lab=0;
        for(i=0;i<=n;i++)
            head[i].clear();
    }
    void add(int u,int v)
    {
        head[u].push_back(v);
        head[v].push_back(u);
    }
    void dfs(int u,int f)
    {
        int i,v,si;
        dfn[u]=Maxdfn[u]=++lab;
        dp[u]=u;
        son[u]=nson[u]=der[u]=nder[u]=inf;
        si=head[u].size();
        for(i=0;i<si;i++)
        {
            v=head[u][i];
            if(v==f)
                continue;
            dfs(v,u);
            dp[u]=min(dp[u],dp[v]);
            Maxdfn[u]=max(Maxdfn[u],Maxdfn[v]);
            if(v<son[u])
            {
                nson[u]=son[u];
                son[u]=v;
            }
            else
            {
                if(v<nson[u])
                    nson[u]=v;
            }
            if(der[u]>dp[v])
            {
                nder[u]=der[u];
                der[u]=dp[v];
                road[u]=v;
            }
            else
                if(nder[u]>dp[v]) nder[u]=dp[v];
        }
        father[u]=f;
    }
    int main()
    {
        int i,j,a,b,t,x,y;
        scanf("%d",&t);
        while(t--)
        {
            init();
            scanf("%d%d",&n,&q);
            for(i=1;i<n;i++)
            {
                scanf("%d%d",&a,&b);
                add(a,b);
            }
            dfs(1,1);
            for(i=1;i<=q;i++)
            {
                scanf("%d%d",&x,&y);
                int ans1,ans2;
                if(head[y].size()==1)
                {
                    puts("no answers!");
                    continue;
                }
                if(dfn[x]<dfn[y]||dfn[x]>Maxdfn[y])
                    printf("%d %d
    ",son[y],der[y]);
                else
                {
                    if(dfn[x]>=dfn[son[y]]&&dfn[x]<=Maxdfn[son[y]])
                        ans1=nson[y];
                    else
                        ans1=son[y];
                    if(dfn[x]>=dfn[road[y]]&&dfn[x]<=Maxdfn[road[y]])
                        ans2=nder[y];
                    else
                        ans2=der[y];
                    if(y!=1) ans1=min(ans1,father[y]),ans2=1;
                    printf("%d %d
    ",ans1,ans2);
                }
            }
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    (整理)REHL6.5_Yum安装Reids
    (整理)REHL6.5_安装本地yum
    (转)MSSQLSERVER执行计划详解
    (转)SQLServer_十步优化SQL Server中的数据访问四
    (转)SQLServer_十步优化SQL Server中的数据访问五
    (转)SQLServer_十步优化SQL Server中的数据访问 三
    (转)SQLServer_十步优化SQL Server中的数据访问 二
    (转)SQLServer_十步优化SQL Server中的数据访问一
    (转)EF5+SQLserver2012迁移到EF6+mysql5.5.47
    (整理)MySQL_REHL6.5 MySQL5.5 中文支持问题
  • 原文地址:https://www.cnblogs.com/wangfang20/p/3243540.html
Copyright © 2020-2023  润新知