P4172 WC2006 水管局長

2021-10-24 19:46:26 字數 3975 閱讀 2560

題目鏈結

題目背景

sc 省 my 市有著龐大的地下水管網路,嘟嘟是 my 市的水管局長(就是管水管的啦)。

題目描述

每天供水公司可能要將一定量的水從 u

uu 處送往 v

vv 處,嘟嘟需要為供水公司找到一條從 u

uu 至 v

vv 的水管的路徑,接著通過資訊化的控制中心通知路徑上的水管進入準備送水狀態,等到路徑上每一條水管都準備好了,供水公司就可以開始送水了。嘟嘟一次只能處理一項送水任務,等到當前的送水任務完成了,才能處理下一項。

在處理每項送水任務之前,路徑上的水管都要進行一系列的準備操作,如清洗、消毒等等。嘟嘟在控制中心一聲令下,這些水管的準備操作同時開始,但由於各條管道的長度、內徑不同,進行準備操作需要的時間可能不同。

供水公司總是希望嘟嘟能找到這樣一條送水路徑,路徑上的所有管道全都準備就緒所需要的時間盡量短。嘟嘟希望你能幫助他完成這樣的乙個選擇路徑的系統,以滿足供水公司的要求。另外,由於 my 市的水管年代久遠,一些水管會不時出現故障導致不能使用,你的程式必須考慮到這一點。

不妨將 my 市的水管網路看作一幅簡單無向圖(即沒有自環或重邊):水管是圖中的邊,水管的連線處為圖中的結點。整張圖共有 n

nn 個節點和 m

mm 條邊,節點從 1

11 至 n

nn 編號。

輸入格式

第一行有三個整數,分別表示管道連線處(結點)的數目 n

nn,目前水管(無向邊)的數目 m

mm,以及你的程式需要處理的任務數目(包括尋找一條滿足要求的路徑和接受某條水管壞掉的事實)qqq。

以下 m

mm 行,每行三個整數 u,v

,tu, v, t

u,v,

t,表示存在一條連線 (u,

v)(u, v)

(u,v

) 的水管,準備時間為 ttt。

以下 q

qq 行,每行三個整數 k,u

,vk, u, v

k,u,

v,描述一項任務。其中 k

kk 表示任務型別:

輸出格式

對於每個 k=1

k = 1

k=1 的任務,輸出一行乙個整數表示答案。

輸入輸出樣例

輸入 #1

443

1222

3334

2142

1142

1411

4

輸出 #1

2

3

說明/提示

資料規模與約定

對於全部的測試點,保證:

題目大意:對乙個簡單無向圖,有兩個操作:

給兩個點,求兩個點之間的路徑的最大邊權的最小值。

刪除圖上的某條邊

對於操作 1

11 有結論:

先證結論 111:

如圖,假設4∼3

−2∼1

4\sim 3 -2\sim1

4∼3−2∼

1是最大邊權最小生成樹上的一條路徑,邊 3,2

3,23,

2 是路徑上權值最大的邊,且權值大於存在非樹邊的路徑 1∼4

1\sim 4

1∼4 上邊權的最大值,顯然斷開邊 3,2

3,23,

2 保留路徑 1∼4

1\sim 4

1∼4 上的非樹邊一定可以使情況一定不會變差。因此假設錯誤,結論 1

11 得證。

結論 2

22 證明:結論 1

11 的策略可以轉化為求最大邊權最小的生成樹:對於新加入的邊,如果邊的兩個端點不在乙個連通塊內則直接加邊,否則如果兩點間路徑中邊權最大的邊大於新加入的邊,則刪掉邊權最大的邊,加入新邊。

按照這個策略求得的是最小生成樹。

因此這個題等價於動態求解求最小生成樹。

由於刪邊操作不好維護,因此可以將問題離線,倒序邊加邊邊求解。策略即結論 2

22 中的策略,用lct維護即可。

#include

#define pii pair

#define fi first

#define se second

using

namespace std;

inline

intqr()

while

(c >=

'0'&& c <=

'9')

return f * fu;

}const

int n =

1e3+

10, m =

1e5+10;

struct lct tr[n + m]

;inline

void

upd(

int p)

inline

bool

get(

int p)

inline

void

spd(

int p)

}inline

bool

isrt

(int p)

inline

void

rot(

int p)

stack<

int> st;

inline

void

pre(

int p)

inline

void

splay

(int p)

inline

void

access

(int p)

inline

void

mkrt

(int p)

inline

void

split

(int x,

int y)

inline

void

link

(int x,

int y)

inline

void

cut(

int x,

int y)

} l;

struct union_find

intget

(int x)

inline

void

merge

(int x,

int y)

} u;

int n, m, q;

struct edge e[m]

, te[m]

;struct

p[m]

;set st;

int id[n]

[n];

int ans[m]

, now, tot;

intmain()

);id[e[i]

.x][e[i]

.y]= i;

}for

(int i =

1; i <= q; i++))

;}for(

auto it:st)te[

++tot]=;

sort

(te +

1, te + tot +1,

[&](edge i, edge j));

u.init

(n);

for(

int i =

1, cnt =

0; i <= tot; i++

)for

(int i = q; i >=

1; i--)}

for(

int i = now; i >=

1; i--

)printf

("%d\n"

, ans[i]);

return0;

}

P4172 WC2006 水管局長

bzoj 那個是加強版 lct 維護動態最小瓶頸樹 題意 給乙個圖,每次詢問兩個點之間路徑的最大值的最小值,或斷開乙個邊,始終保證圖連通 用 lct 維護,發現斷邊不怎麼好做,所以離線下來倒序處理,常規套路 就是先跑乙個最小瓶頸生成樹,然後每次加邊,如果加的這個邊的邊權大於它兩個端點間原來路徑的最大...

P4172 WC2006 水管局長

傳送門 顯然 lct 動態維護最小生成樹 詢問就是問樹上兩點的路徑中權值最大的邊 為了維護邊權,我們要把邊也看成點,為了方便,邊在 lct 中的編號為 n 1 到 n m 因為正做不好維護刪邊,所以離線倒過來,變成加邊 在反過來做的時候,為了維護最小生成樹要知道哪些邊被刪除了 用 set 或者 ma...

洛谷P4172 WC2006 水管局長

lct動態維護最小生成樹的典例 這個都是套路,倒序處理,將刪邊變成加邊 再將邊換成點,然後就可以做到點權維護邊權資訊 說一下加邊的過程大概是 一 首先最小生成樹,保證初始最優 二 對於新加入的一條邊,找出原x y鏈上的最大邊,替換 第二點的實現比較有意思 因為是在樹上加邊,所以一定會形成乙個環,那麼...