先貼上位址
判斷有根樹同構:
1. 直接用括號最小表示法
2. 利用括號最小表示法的思想進行hash
判斷無根樹同構:
1. 找到樹的重心.
2. 以重心為根, 把無根樹轉化成有根樹. 按照有根樹同構的方法判斷是否同構.
同構的過程中,為什麼可以sort.
我們知道,對於樹來說,
樹的節點繞著它的父節點旋轉,樹的結構就不會被改變的.
所以sort的過程就相當於把樹的節點繞著它的父節點進行旋轉.
// sort的話,可以這麼理解:
我們是按照同樣的規則(我們保證這個規則可以唯一確定一棵樹,),
對兩棵樹進行操作,如果同構的話,那麼結果應該是一樣的. 如果不同構的畫 那麼結果就是不一樣的
至於樹的括號表示式, 可以見這幾個部落格
括號表示式
樹同構
樹的表示方法
#include #include#include
#include
#include
#include
#include
using
namespace
std;
typedef unsigned
long
long
ull;
const
int maxn = 1e5+10
;ull x[maxn];
intans[maxn];
struct
edge ;
class
tree
int dfs(int u, int
fa)
return res + 1
; }
ull dfs2(
int u, int fa, int
deep)
sort(son.begin(), son.end());
//判斷樹同構 注意要sort後乘乙個隨機數(或者乙個質數的i次方). 為什麼可以sort呢? 因為樹同一層的節點圍繞父節點旋轉不會改變樹的結構. 而sort相當於把節點繞父節點旋轉了.
for (i=0, t1=son.size(); ii)
res += son[i] * x[i+1
];
return cnode[u] = (res ?res : x[deep]);
}void init(int
n)
if (!(v =id[s2]))
add(u, v); add(v, u);
}dfs(
1, -1
);
int mm = 0x3f3f3f3f
;
for (i=1; i<=n; ++i)
else
if (mm == rcd[i]) mid[++ccnt] =i;
}for (i=1; i<=ccnt; ++i)
vvvvv[i] = dfs2(mid[i], -1, 1
); }
}te1, te2;
struct
nobe
nobe () {}
nobe (
intiid, ull vval) : id(iid), val(vval) {}
};void dfs3(int u1, int u2, int fa1, int
fa2)
for (i=te2.head[u2]; i; i=te2.edge[i].lst)
sort(ve1.begin(), ve1.end());
sort(ve2.begin(), ve2.end());
for (i=0, tsz=ve1.size(); ii)
dfs3(ve1[i].id, ve2[i].id, u1, u2);
}int
main()
}a: ;
}return0;
}
洛谷P5043 樹的同構(樹hash)
這題就是無腦,萌新不知道什麼叫樹的重心,也不知道什麼叫最小表示法排序,萌新只會無腦hash 對每一棵樹,每乙個節點為根跑一次hash值,強行判斷就好 最後用並查集維護一下,其他看 吧 include include include include include include using name...
無根樹轉有根樹
乙個n n 1000000 個結點的無根樹的各條邊,並指定乙個根結點,要求把樹轉化為有根樹。輸入 結點的數目n,無根樹的各條邊,輸入乙個根結點號。輸出 各個結點的父親編號。執行結果 演算法實現 為方便起見,我們用了stl中的vector來儲存邊,g u 表示u結點的相鄰結點的編號。樹的儲存結構定義 ...
無根樹變為有根樹
即無環連通無向圖 若乙個圖中每條邊都是無方向的,則稱為無向圖。無根樹它要求每個頂點之間都直接或間接相連,且圖中無環,即只有簡單路徑。由於樹是圖的子集,這一類圖具有樹的特徵,但不具有樹狀的形式,沒有特定的根節點,故稱為無根樹。任意選取圖中某個點為根,均可將無根樹轉化為有根樹。includeusing ...