# 拉拉啦啦啦啦啦啦 嘿,有心情再看我這篇亂寫的東東._. ``` cpp= #include <iostream> #include <vector> using namespace std; vector <int> link[10005]; int now[10005]; int goal[10005]; int v[10005]; int dfs(int k) { int cnt=0; if(now[k]!=goal[k]) { now[k]=goal[k]; cnt++; } for(int j=0;j<link[k].size();j++) { int point; link[k][j]=point; for(int m=0;m<link[point].size();m++) { if(link[point][m]==0) link[point][m]=1; else if(link[point][m]==1) link[point][m]=0; } } for(int i = 0;i<link[k].size(); i++) { dfs(link[k][i]); } cout<<cnt<<endl; return 0; } int main() { int n; cin>>n; int x,y; for(int i=0;i<n;i++) { cin>>x>>y; link[x].push_back(y); link[y].push_back(x); } for(int i=0;i<n;i++) cin>>now[i]; for(int i=0;i<n;i++) cin>>goal[i]; dfs(1); return 0; } ``` 1. 研究為什麼沒有輸出東西 可以先找找看程式卡在哪個地方,一個比較常見的方法就是在一些地方輸出(cout)東西。(這個方法在以後寫大型專案就比較不推薦了) 如果是我的話,我會先嘗試在第10行那邊先輸出看看,因為dfs比較容易出錯 ``` cpp=9 int dfs(int k) { cout << k << endl; ... } ``` 應該會發現沒有印出東西,表示dfs沒有被執行到。那就再檢查執行dfs之前,看看哪邊有出錯,仔細看看會發現邊只要輸入n-1條所以把第41行改掉就會印出東西了。 ``` cpp=41 for(int i = 0; i < n - 1; i++) { } ``` 補充一下,一棵樹=>無向無環的結構,他會剛好有n-1條邊(n是點的數量)。 2. dfs的小問題 改好輸入問題,程式可能還是沒有照常運作,但沒關係,我們用前面的方法試試看,在第10行下面輸出k,看看dfs(int)是怎麼被呼叫的 那這邊就直接破梗,這邊寫反了拉XD ``` cpp=20 link[k][j]=point; // point = link[k][j] ``` 改完之後,會發現有些點會重複走訪,也就是說,要記得紀錄哪些點走訪過,這樣就不會重複走到。比如說1和2之間有一條邊,那從1走到2之後,接著從點2繼續往下走,他會走回1。 這邊放個dfs的基本架構 ``` cpp void dfs(int u) { visit[u] = true; for(int v : e[u]) if(visit[v] == false) { // 還沒被走訪過的話,才繼續dfs dfs(v); } } ``` 那因為題目是給一棵樹,dfs由上到下,只會從父節點往下走,所以只要紀錄上一個節點是從哪裡來的,不要回到上一個節點,就沒問題了 ``` cpp void dfs(int u, int parent) { for(int v : e[u]) if(v != parent) { dfs(v, u); } } ``` 再補充一下,這兩個寫法一樣喔 ``` cpp vector<int> v = {1, 2, 3, 4}; for(int i = 0; i < v.size(); i++) cout << v[i] << ' '; for(int t : v) cout << t << ' '; ``` 最後再提示一下解法,題目說,每次做更改,在當前節點下方,距離為偶數的節點也要做更改。 你的寫法看起來像是在每次做更改的時候,就把子樹做一次更新,原本你的下法理論上只會改到下下一層,不會對下下下下一層做更改。要對整個子樹做更新,就必須再做一次dfs,寫起來會像這樣 ``` cpp void dfs2(int k, int parent, int layer) { if(layer % 2 == 0) { // 距離更改的點為偶數 if(now[k] == 0) now[k] = 1; else if(now[k] == 1) now[k] = 0; } for(int u : link[k]) if(u != parent) { dfs(u, k, layer + 1); } } int dfs(int k, int parent) { int cnt=0; if(now[k]!=goal[k]) { // 不一樣,對子樹做更新 cnt++; dfs2(k, parent, 0); } . . } ``` 這個做法的時間複雜度會是$O(n^2)$,想像每次都要更新接近n個點,最多要更新約n次 那優化的部分就交給你再想一下了,好像分別紀錄深度為偶數和奇數的點,需要更新幾次就... :D