題意:求曼哈頓距離最小生成樹第k大的邊。曼哈頓距離:點a(x1,y1)與點b(x2,y2)距離d=abs(x1-x2)+abs(y1-y2)。
求解曼哈頓距離最小生成樹的方法簡述:
如果直接兩兩點建邊,總邊數則為o(n2)條,用時間複雜度o(n+e)的prim演算法,時間複雜度o(e*loge)的kruskal演算法都是會超時的(這裡n為點數,e為邊數)
而這裡的解題思路就是將邊數複雜度降到o(n),因為大量的邊是沒有用到的,只要每45度方向距離該點最近的乙個點連邊即可。
證明就不證了,直接上結論,假如b,c都是a 在y
'>y
軸向右45度區域內並且
依據上面可得只要連線每個點與八個方向距離最小的點連邊即可。
又因為,邊是雙向的,我們只要連r1,r2,r3,r4四個方向即可。比如:(上圖)b是a r1最小距離點,a是b r5最小距離點,我們只要連r1,r5不連,即a連向b即可知道ab的關係。
思路出來了,那麼怎麼處理呢?我們先考慮乙個方向,例如r1,(其他三個方向模擬即可)。
在某個點a(x
0,y0
)'>a(x0,y0)
的這個區域內的點b(x
1,y1
)'>b(x1,y1)
滿足x1≥x
0'>x1≥x0 且y1
−x1>y0
−x0'>y1−x1>y0−x0
。那麼b就在a的r1上|ab
|=y1
−y0+
x1−x
0=(x
1+y1
)−(x
0+y0
)'>。a(
x0,y
0)'>b(x
1,y1
)'>x1≥
x0'>y1−
x1>y0
−x0'>|ab
|=y1
−y0+
x1−x
0=(x
1+y1
)−(x
0+y0
)'>在a
'>a
的r1區域內距離a
'>a
最近的點也即滿足條件的點中x+y
'>x+y
最小的點。因此我們可以將所有點按x
'>x
座標排序,再按y−x
'>y−x
離散。a(x
0,y0
)'>b(x
1,y1
)'>x1≥
x0'>y1−
x1>y0
−x0'>|ab
|=y1
−y0+
x1−x
0=(x
1+y1
)−(x
0+y0
)'>a
'>a
'>x+y
'>x
'>y−x
'>用線段樹或者樹狀陣列維護大於當前點的y−x
'>y−x
的最小的x+y
'>x+y
對應的點(也就是維護區間最小值)這裡用的是樹狀陣列,因為**較簡單。a(
x0,y
0)'>b(x
1,y1
)'>x1≥
x0'>y1−
x1>y0
−x0'>|ab
|=y1
−y0+
x1−x
0=(x
1+y1
)−(x
0+y0
)'>a
'>a
'>x+y
'>x
'>y−x
'>y−x
'>x+y
'>樹狀陣列知識:
x0,y
0)'>b(x
1,y1
)'>x1≥
x0'>y1−
x1>y0
−x0'>|ab
|=y1
−y0+
x1−x
0=(x
1+y1
)−(x
0+y0
)'>a
'>a
'>x+y
'>x
'>y−x
'>y−x
'>x+y
'>這樣r1區域就處理完了,而其他三個區域的點只要用數學知識 翻轉和對稱 轉化成r1處理即可。比如,r2區域將關於y=x對稱(即swap(x,y)),再將關於a(
x0,y
0)'>b(x
1,y1
)'>x1≥
x0'>y1−
x1>y0
−x0'>|ab
|=y1
−y0+
x1−x
0=(x
1+y1
)−(x
0+y0
)'>a
'>a
'>x+y
'>x
'>y−x
'>y−x
'>x+y
'>x軸對稱(即x=-x)可求r3,再關於y=x對稱求r4。a(
x0,y
0)'>b(x
1,y1
)'>x1≥
x0'>y1−
x1>y0
−x0'>|ab
|=y1
−y0+
x1−x
0=(x
1+y1
)−(x
0+y0
)'>a
'>a
'>x+y
'>x
'>y−x
'>y−x
'>x+y
'>還有些細節可以看**:a(
x0,y
0)'>b(x
1,y1
)'>x1≥
x0'>y1−
x1>y0
−x0'>|ab
|=y1
−y0+
x1−x
0=(x
1+y1
)−(x
0+y0
)'>a
'>a
'>x+y
'>x
'>y−x
'>y−x
'>x+y
'>**:
#include#include#include
#include
#include
#include
#define inf 0x3f3f3f3f
using
namespace
std;
typedef
long
long
ll;const
int maxn=1e5;
struct
point
}p[maxn];
//按x從小到大排序,再按y-x離散
struct
node
}edge[maxn
<<3
];struct bit
}bit[maxn];
int fa[maxn],a[maxn],b[maxn];//
陣列a,b用於離散化,求得 在y軸向右45度的所有點
intn,m,k,cnt;
int find(int
x)void add(int u,int v,int
w)int lowbit(int x)
int dist(point a,point b)
int query(int x,int m)
}return
pos;
}void update(int x,int y,int pos)
}}void solve()
if(tot==k)
}}void
caledge()
}int
main()
solve();
return0;
}
關於曼哈頓距離的最小生成樹 POJ3241
題目位址 題目就是給你n個點 求n個點的曼哈頓距離的最小生成樹 輸出所有邊中第k大的的邊的權重。n個點那麼有有n n 1 條邊如果採用樸素的prim演算法建邊就是o n2 的複雜度,我們來考慮一下曼哈頓距離的特殊性,其實不是所有的邊都需要,在建邊的時候就可以去掉很多多餘的邊。如圖,對於給定的一些點我...
POJ 3241(曼哈頓距離,MST)
2015 04 29 21 58 58 題目 題意有先爭議.其實出題人就是想考 求曼哈頓距離最小生成樹上的第k大的邊。關於 manhattan mst 的介紹 部落格。然後就是比較裸的問題了.最後用kruskal找第k大的邊。過程基本上可以簡述為 1 將所有點經歷四種變換 不變,y x對稱,y 0對...
曼哈頓距離最小生成樹
一 前人種樹 部落格 曼哈頓距離最小生成樹與莫隊演算法 部落格 學習總結 最小曼哈頓距離生成樹 二 知識梳理 曼哈頓距離 給定二維平面上的n個點,在兩點之間連邊的代價。即distance p1,p2 x1 x2 y1 y2 曼哈頓距離最小生成樹問題求什麼?求使所有點連通的最小代價。最小生成樹的 環切...