@@ -1115,6 +1115,7 @@ func (*graph) shortestPathDijkstra(in io.Reader, n, m, st int) (dist []int64) {
1115
1115
// EXTRA: 次短路
1116
1116
// 模板题 https://www.luogu.com.cn/problem/P2865
1117
1117
// LC2045/周赛263D https://leetcode-cn.com/problems/second-minimum-time-to-reach-destination/
1118
+ // 次短路径计数 https://www.acwing.com/problem/content/385/
1118
1119
{
1119
1120
const inf int64 = 1e18 // 1e9+1
1120
1121
dist := make ([]int64 , n )
@@ -1852,6 +1853,103 @@ func (*graph) strictlySecondMST(n int, edges []struct{ v, w, wt int }, min, max
1852
1853
return mstSum
1853
1854
}
1854
1855
1856
+ // 曼哈顿距离最小生成树 O(nlogn)
1857
+ // LC1584 https://leetcode-cn.com/problems/min-cost-to-connect-all-points/
1858
+ // 做法见官方题解 https://leetcode-cn.com/problems/min-cost-to-connect-all-points/solution/lian-jie-suo-you-dian-de-zui-xiao-fei-yo-kcx7/
1859
+ func (* graph ) manhattanMST (points []struct { x , y , i int }, abs func (int ) int ) (mst int ) {
1860
+ n := len (points )
1861
+ // 读入时把 points 加上下标
1862
+
1863
+ type edge struct { v , w , dis int }
1864
+ edges := []edge {}
1865
+
1866
+ build := func () {
1867
+ sort .Slice (points , func (i , j int ) bool { a , b := points [i ], points [j ]; return a .x < b .x || a .x == b .x && a .y < b .y })
1868
+
1869
+ // 离散化 y-x
1870
+ type pair struct { v , i int }
1871
+ ps := make ([]pair , n )
1872
+ for i , p := range points {
1873
+ ps [i ] = pair {p .y - p .x , i }
1874
+ }
1875
+ sort .Slice (ps , func (i , j int ) bool { return ps [i ].v < ps [j ].v })
1876
+ kth := make ([]int , n )
1877
+ k := 1
1878
+ kth [ps [0 ].i ] = k
1879
+ for i := 1 ; i < n ; i ++ {
1880
+ if ps [i ].v != ps [i - 1 ].v {
1881
+ k ++
1882
+ }
1883
+ kth [ps [i ].i ] = k
1884
+ }
1885
+
1886
+ const inf int = 2e9
1887
+ tree := make ([]int , k + 1 )
1888
+ idRec := make ([]int , k + 1 )
1889
+ for i := range tree {
1890
+ tree [i ] = inf
1891
+ idRec [i ] = - 1
1892
+ }
1893
+ update := func (pos , val , id int ) {
1894
+ for ; pos > 0 ; pos &= pos - 1 {
1895
+ if val < tree [pos ] {
1896
+ tree [pos ] = id
1897
+ idRec [pos ] = id
1898
+ }
1899
+ }
1900
+ }
1901
+ query := func (pos int ) int {
1902
+ minVal , minID := inf , - 1
1903
+ for ; pos < len (tree ); pos += pos & - pos {
1904
+ if tree [pos ] < minVal {
1905
+ minVal = tree [pos ]
1906
+ minID = idRec [pos ]
1907
+ }
1908
+ }
1909
+ return minID
1910
+ }
1911
+
1912
+ for i := n - 1 ; i >= 0 ; i -- {
1913
+ p := points [i ]
1914
+ pos := kth [i ]
1915
+ if j := query (pos ); j != - 1 {
1916
+ q := points [j ]
1917
+ dis := abs (p .x - q .x ) + abs (p .y - q .y )
1918
+ edges = append (edges , edge {p .i , q .i , dis })
1919
+ }
1920
+ update (pos , p .x + p .y , i )
1921
+ }
1922
+ }
1923
+ build ()
1924
+ for i := range points {
1925
+ points [i ].x , points [i ].y = points [i ].y , points [i ].x
1926
+ }
1927
+ build ()
1928
+ for i := range points {
1929
+ points [i ].x = - points [i ].x
1930
+ }
1931
+ build ()
1932
+ for i := range points {
1933
+ points [i ].x , points [i ].y = points [i ].y , points [i ].x
1934
+ }
1935
+ build ()
1936
+
1937
+ sort .Slice (edges , func (i , j int ) bool { return edges [i ].dis < edges [j ].dis })
1938
+
1939
+ uf := newUnionFind (n )
1940
+ left := n - 1
1941
+ for _ , e := range edges {
1942
+ if uf .merge (e .v , e .w ) {
1943
+ mst += e .dis // int64
1944
+ left --
1945
+ if left == 0 {
1946
+ break
1947
+ }
1948
+ }
1949
+ }
1950
+ return
1951
+ }
1952
+
1855
1953
// Kruskal 重构树
1856
1954
// https://oi-wiki.org/graph/mst/#kruskal_1
1857
1955
0 commit comments