給定
n 個點,
m條邊的無向圖。每個點有點權wi
,一條邊(x
,y) 的邊權定義為|w
x−wy
| 。 有q
詢問,每次詢問兩個點(x
,y),如果
x 和
y之間存在至少兩條互不相交(沒有重複邊)的路徑,那麼輸出這兩條路徑上邊權的最大值(如果有多對路徑,選擇最小的),否則輸出−1
。3≤n
≤105,
3≤m≤
5×105
,1≤q
≤105
考慮一種最暴力的做法,按邊權從小到大插入邊,動態維護邊雙連通分量。連通分量內的答案可以瞎處理。然而這樣很難維護。
怎麼辦呢?用最小生成樹來維護乙個聯通性,這樣然後在樹上可以更方便的處理邊雙內路徑的最大權值。我們可能會加入某些邊使得它有環,那麼環內權值就要變成加入這條邊的權值(加入邊肯定更大)。但是修改過一次的邊我們就不能再修改了,因為顯然它達到了條件且不會更優。因此我們使用並查集來將所有修改過的點並在一起,這樣修改時就可以暴力沿著並查集父親修改了。
處理詢問的話,倍增查詢路徑最大值即可。
時間複雜度o(
nlog2n
) 。
#include
#include
#include
#include
#include
using
namespace
std;
int read()
int buf[30];
void write(int x)
const
int n=100050;
const
int m=500050;
const
int e=n<<1;
const
int lgn=17;
struct edge
e[m];
bool
operator
<(edge a,edge b)
void insert(int x,int y,int z)
void dfs(int x)
void pre()
int adjust(int x,int d)
void getans(int x,int y)
int main()
}anc[1][0]=0,deep[1]=1,dfs(1);
for (int i=1;i<=n;i++) fa[i]=i;
for (int i=1,x,y;i<=m;i++)
if (!chosen[i])
for (x=getfather(e[i].x),y=getfather(e[i].y);x!=y;x=getfather(x))
pre();
for (int x,y;q--;)
fclose(stdin),fclose(stdout);
return
0;}
51nod1743 雪之國度
對於乙個無向圖,邊有邊權。對於每組詢問u v,如果可以找到兩條從u到v不相交的路徑,輸出路徑上邊權最大值的最小值。我們考慮到,如果按照邊權從小到大加邊,第一次使得u和v處在同乙個邊雙聯通分量時我就求得了答案。考慮乙個很強的方法,用lct或啟發式合併維護森林,動態維護雙連通分量。因為不可能去持久化 二...
JZOJ 雜題選講 51nod1790
有乙個初始為0的計數器n,每次有兩種操作 n 1 把n不含前導0的二進位制接到字串s的末尾 目標是把s變成給出的字串x 求方案數和最小步數 x 5000 設f i j 表示放到x的第i位,n為 j,i 的方案,最小值同理 每次列舉上乙個位置轉移,這樣是o x 3 並且不好判斷二進位制數的大小 按x的...
51nod 4級演算法 1405
給定一棵無根樹,假設它有n個節點,節點編號從1到n,求任意兩點之間的距離 最短路徑 之和。第一行包含乙個正整數n n 100000 表示節點個數。後面 n 1 行,每行兩個整數表示樹的邊。output每行乙個整數,第i i 1,2,n 行表示所有節點到第i個點的距離之和。4 1 23 2 4 253...