• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            算法學(xué)社
            記錄難忘的征途
            posts - 141,comments - 220,trackbacks - 0
            題目描述:
                給一顆結(jié)點(diǎn)數(shù)為(100,000)的樹,最多詢問100,000次。每次詢問對(duì)兩個(gè)結(jié)點(diǎn)X,Y,以X為根,Y的最小標(biāo)號(hào)的孩子,Y的最小標(biāo)號(hào)的后代。
            吐槽:
                1. 這么難寫的題為什么大家都當(dāng)水題做阿...
            算法分析:
                
                對(duì)于X,Y,我們求出其LCA,U。
                如果U是Y的父親,那么一切都不變。用預(yù)處理的結(jié)果就可以。
                如果U是Y,那么我們可以快速求出,含有后代X的Y的兒子X'。
                檢查X'是否是Y的最小孩子(兒子)。如果是,那么結(jié)果是Y的次小兒子(孩子)。否則是Y的最小兒子(孩子)。
                于是我們樹形DP,求出最小與次小(兒子,后代)就可以了。寫起來(lái)很猥瑣,容易出錯(cuò)。
                LCA的寫法是參照shi哥的代碼。
                先預(yù)處理求出u的(1,2,4,8,...)代祖先,
                先讓x,y處于同一層。
                然后讓x,y一點(diǎn)一點(diǎn)向上爬,直到爬到恰好x==y的位置就是LCA了。
                
            #include<iostream>
            #include<cassert>
            #include<cstdio>
            using namespace std;
            const int maxb = 17;
            const int V = 1<<maxb;
            int e,P[V][maxb], head[V], nxt[V<<1], pnt[V<<1], mn[V], sd[V], mn1[V],sd1[V];
            // dp
            const int inf = ~0u>>2;
            int dep[V];
            void dfs(int u,int f){
                P[u][0] = f;
                for(int i =1; i< maxb; i++)
                    P[u][i] = P[P[u][i-1]][i-1];
                if(f!=u) mn[u] = f; else mn[u] = inf;
                mn1[u] = sd1[u] = inf;
                sd[u] = inf;
                for(int i=head[u];i!=-1;i=nxt[i]) {
                    int v = pnt[i];
                    if(v == f) continue;
                    dep[v] = dep[u] + 1;
                    if(v < mn[u]) {sd[u] = mn[u]; mn[u] = v;}
                    else if(v < sd[u]) sd[u] = v;
                    dfs(v,u);
                    int fst,snd;
                    if(v > mn1[v]) {
                        fst = mn1[v];
                        snd = min(v, sd1[v]);
                    }
                    else {
                        fst = v;
                        snd = mn1[v];
                    }
                    if(fst < mn1[u]){
                        sd1[u] = mn1[u];
                        mn1[u] = fst;
                    }
                    else {
                        sd1[u] = min(sd1[u],fst);
                    }
                }
            }
            // build
            void add(int u,int v){
                nxt[e] = head[u];
                head[u] = e;
                pnt[e++] = v;
            }
            // LCA
            void go(int &u,int d){
                for(int i=0;i<maxb;i++){
                    if((1<<i) & d) u = P[u][i];
                }
            }
            int LCA(int x,int y){
                if(dep[x] > dep[y]) swap(x,y);
                go(y,dep[y] - dep[x]);
                if(x == y) return x;
                for(int i=maxb-1;i>=0;i--){
                    if(P[x][i] != P[y][i])
                        x = P[x][i], y = P[y][i];
                }
                assert(P[x][0]==P[y][0]);
                return P[x][0];
            }
            // work
            void work(int x,int y){
                int u = LCA(x,y);
                if(sd[y] == inf) {puts("no answers!"); return;}
                if(u!=y){
                    printf("%d %d\n",P[y][0] == mn[y] ? sd[y] : mn[y], mn1[y]);
                }
                else {
                    go(x,dep[x]-dep[y]-1);
                    
                    printf("%d %d\n",x == mn[y] ? sd[y]: mn[y] , y == 1 ? (min(mn1[x],x) == mn1[y]? sd1[y]: mn1[y]): 1);
                }
            }
            int main(){
                int test;
                scanf("%d",&test);
                while(test--){
                    int u,v,n,m;
                    e = 0;
                    scanf("%d%d",&n,&m);
                    for(int i=1;i<=n;i++) head[i] = -1;
                    for(int i=1;i<n;i++){
                        scanf("%d%d",&u,&v);
                        add(u,v);
                        add(v,u);
                    }
                    dep[1] = 0;
                    dfs(1,1);
                    while(m--){
                        scanf("%d%d",&u,&v);
                        work(u,v);
                    }
                    puts("");
                }
            }
            posted on 2012-07-17 10:53 西月弦 閱讀(500) 評(píng)論(0)  編輯 收藏 引用 所屬分類: 解題報(bào)告
            国产成人综合久久久久久| 伊人久久成人成综合网222| 久久婷婷五月综合97色一本一本| 囯产极品美女高潮无套久久久| 狠狠综合久久AV一区二区三区| 亚洲综合伊人久久大杳蕉| 午夜精品久久久久久| 欧美精品九九99久久在观看| 久久久久人妻精品一区| 91久久九九无码成人网站| 久久九九有精品国产23百花影院| 99久久国产综合精品五月天喷水| 久久精品国产久精国产一老狼| 久久久青草久久久青草| 久久久久精品国产亚洲AV无码 | 伊人伊成久久人综合网777| 久久无码人妻一区二区三区 | 五月丁香综合激情六月久久| 精品一区二区久久| 久久久久亚洲AV无码专区首JN| 亚洲伊人久久大香线蕉苏妲己| 中文字幕乱码久久午夜| 青青青青久久精品国产h久久精品五福影院1421 | 热久久这里只有精品| 久久影院综合精品| 国产亚洲精久久久久久无码77777| 国产精品美女久久久| 一本综合久久国产二区| 久久精品中文字幕第23页| 九九精品99久久久香蕉| 亚洲精品无码成人片久久| 日韩欧美亚洲综合久久影院Ds| 四虎国产精品免费久久久| 久久精品人人做人人爽电影| 久久久亚洲欧洲日产国码二区 | 久久免费的精品国产V∧| 久久无码国产专区精品| 久久精品综合一区二区三区| 国产精品无码久久综合网| 国产成人精品久久| 久久精品国产亚洲7777|