ZOJ 1141 簡單的題目就用簡單的代碼

前言

因為我在做題目的過程中,WA了(最后發(fā)現(xiàn)是數(shù)組開小了的緣故),我以為我方法錯誤。然后百度一下,滿屏的LCA在線/離線算法。加上長篇代碼。為了拯救茫茫的ACMer,我決定吐槽一下在這題中使用LCA算法的人

附上 LCA算法的簡介

題意

給出一顆樹,給出若干個查詢,每個查詢是樹的兩個節(jié)點,要求的是這兩個節(jié)點的最近公共祖先。最后總計每個數(shù)作為最近公共祖先出現(xiàn)的次數(shù)。說白了就是最近公共祖先問題。

解析

的確,LCA是用于求最近公共祖先的一種有效算法,但是由于思想比較復(fù)雜(從根節(jié)點開始搜索)且代碼量太大了(隨便找了一篇就是180行的長度),所以在這里并不推薦用。如果只是要A這道題,那大可以這樣

比如要查(3,4)最近公共祖先
3開始往上走,得到:[3,2,5]
4開始往上走,得到:[4,5]
然后倒序遍歷,55相同,繼續(xù)比較24,24不同,則上一個公共祖先 5 就是最近的公共祖先

再比如要查(2,3)最近公共祖先
2開始往上走,得到:[2,5]
3開始往上走,得到[3,2,5]
然后倒序遍歷,55相同,繼續(xù)比較22也相同,繼續(xù)比較3X(X表示越界,比較失敗),則上一個公共祖先2就是最近的公共祖先

LCA算法在于從根節(jié)點開始遍歷,在深度優(yōu)先搜索的過程中對結(jié)點進行“染色”操作。我覺得至少在這里,貌似簡單的“白話文”(如上題解過程)更能讓人理解,簡單的題目,就用簡單的理解+簡單的代碼,簡單也是一種習(xí)慣

AC代碼

#include <iostream>
#include <stdio.h>
#include <string.h>
#define maxn 101000
using namespace std;
int dp1[maxn],dp2[maxn],dp[maxn],tree[maxn];
int main(int argc, const char * argv[]) {
    int n,m,p,d,len1,len2;
    char ch;
    while(cin>>n){
        memset(dp, 0, sizeof(dp));
        memset(tree, 0, sizeof(tree));
        while(n--){
            scanf("%d:(%d)",&p,&d);
            for(int i=0; i<d; i++){
                scanf("%d",&m);
                tree[m] = p;
            }
        }
        cin>>m;
        for(int j=0; j<m; j++){
            len1 = 0; len2 = 0;
            cin>>ws>>ch>>p>>ch>>d>>ch;
            while(p){
                dp1[len1++] = p;
                p = tree[p];
            }
            while(d){
                dp2[len2++] = d;
                d = tree[d];
            }
            while(dp1[--len1]==dp2[--len2]);
            dp[dp1[len1+1]]++;
        }
        for(int i=1; i<=1010; i++)
            if(dp[i]) cout<<i<<":"<<dp[i]<<endl;
    }
    return 0;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容