多校1009 (DFS+樹狀數組)

來源:互聯網
上載者:User
 

暴力N^2 各種TLE

#include <cstdio>
#include <string.h>
const int maxn=100010;
struct node
{
    int v;
    node *next;
    node (int a ,node * p):v(a),next(p){};
};
node * List[maxn];
int min_num[maxn],deg[maxn],n,son[maxn];
int n2;
bool vis [maxn];
void dfs (int u)
{
    vis[u]=true ;
    if(!(deg[u]^1))return ;
    int v,i;
    int pre=0,back=0,tmp=0;

    if(u<n2)
    {
        for (i=0 ; i<u ; i++)
        if(vis[i])pre++;
    }
    else
    {
        for(i=u+1 ; i<n ; i++)
        if(vis[i])pre++;
    }

    node * p =List[u];

    for (; p!=NULL ; p=p->next)
    {
        v=p->v;
        //printf("u=%d v=%d \n",u,v);
        if(!vis[v])
        {
            dfs(v);
            son[u]+=son[v];
        }

    }

    if(u<n2)
     {
        for (i=0 ; i<u ; i++)
        if(vis[i])back++;
        min_num[u]=back-pre;
     }
    else
    {
        for (i=u+1 ; i<n ; i++)
        if(vis[i])back++;
        min_num[u]=son[u]-back+pre-1;
    }
    //printf("%d,%d %d  %d\n",pre,back,u ,son[u]);

}

void init ()
{
    memset (List , 0 , sizeof(List));
    memset (deg , 0 , sizeof(deg));
    memset (vis , 0 , sizeof(vis));
    n2=n/2;
}

int main ()
{
    int p,i,j,u,v;
    node *tmp1 ;
    node *tmp2 ;
    while (scanf("%d%d",&n,&p)==2 && (n||p))
    {
        init();
        for (i=1 ; i<n ; ++i)
        {
            scanf("%d%d",&u,&v);
            u-- , v--;
            tmp1=new node(v,NULL);
            List[u]==NULL?List[u]=tmp1:(tmp1->next=List[u],List[u]=tmp1);
            /*tmp2=new node(u,NULL);
            List[v]==NULL?List[v]=tmp2:(tmp2->next=List[v],List[v]=tmp2);*/
            deg[u]++;deg[v]++;
            son[i]=1;
        }
        son[0]=0;
        p--;
        vis[p]=true ;
        node * tp=List[p];
        min_num[p]=p;
        for (; tp!=NULL ; tp=tp->next)
        {
            v=tp->v;
            if(!vis[v])
                dfs(v);
        }

        for (int i=0 ; i<n ; ++i)
         printf("%d%c",min_num[i],i==n-1?'\n':' ');
    }
    return 0;
}

 正解演算法 用樹狀數組

 題 目 大 意 是 給 定 一 棵 樹 ,對 於 每 個 節 點 ,計 算 其 所 有 子 節 點 中 編 號 小 於 該 節 點 編 號 的 個
數 。 記 所 求 為 f[i], 根 據 樹 的 遞 歸 性 質 我 們 可 以 想 到 對 其 進 行 遞 歸 統 計 。 我 們 可 以 使 用 一 個
樹 狀 數 組 記 錄 當 前 加 入 的 節 點 。 每 當 遍 曆 到 一 個 節 點 時 ( 注 意 是 後 序 ), 便 將 該 節 點 加 入 ,
那 麼 當 我 們 遍 曆 完 以 V 為 根 的 所 有 子 樹 時 , 便 可 以 根 據 加 入 的 節 點 計 算 出 f[v ]。
     這 裡 有 一 個 小 問 題 :假 設 U ,V 為 兄 弟 節 點 ,我 們 首 先 遍 曆 了 以 U 為 根 的 子 樹 ,當 我 們
遍 曆 以 V 為 根 的 子 樹 時 ,U 子 樹 的 所 有 節 點 已 經 加 入 了 ,然 而 它 們 並 不 屬 於 V 中 任 意 節 點 的
子 節 點 。 但 注 意 到 V 的 所 有 子 節 點 都 是 在 遍 曆 到 V  子 樹 之 後 才 加 入 的 , 所 以 我 們 可 以 在 遍
曆 V 節 點 的 子 節 點 之 前 記 錄 當 前 編 號 小 於 V 的 節 點 總 數 C 1 , 在 遍 曆 完 所 有 子 樹 之 後 計 算 編
號 小 於 V 的 節 點 總 數 C 2, 則 有 f[v ]= C 2-C 1 。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.