HNOI2014 道路堵塞 最短路,線段樹

2022-06-07 07:06:10 字數 1377 閱讀 7448

對不起對不起,辣雞蒟蒻又來用核彈打蚊子了

完全ignore了題目給出的最短路,手工搞出乙個最短路,發現對答案沒什麼影響

所以乾脆轉化為經典問題:每次詢問刪掉一條邊後的最短路

如果刪掉的是非最短路邊,那麼顯然毫無影響

如果刪掉的是最短路邊,那麼我們倒過來,考慮這個時候每條非最短路邊的貢獻。對於一條非最短路邊 \((u,v)\) ,我們很容易得到一定包含它的最短路一定是滿足 \(1 \to x \to u \to v \to y \to n\) 這樣的結構,其中 \(x,y\) 都在選定的最短路上,那麼只要刪除的是最短路上 \(x \sim y\) 之間的邊,這個貢獻就是存在的。

考慮如何求出對 \((u,v)\) 的 \(x,y\) ,跑完最短路後搞出最短路徑樹,那麼最短路顯然是最短路徑樹的一條鏈。對這條鏈上任意乙個點 \(p\) ,對它所有不在鏈上的兒子 \(q\) ,我們將每乙個 \(q\) 的子樹都打上 \(p\) 標記,表示從 \(1\) 到這些點的最短路在 \(p\) 點與選定的 \(1 \sim n\) 最短路分開

因此我們維護刪掉最短路上每條邊時的答案,這是乙個序列。列舉每條非最短路邊去計算它的貢獻與貢獻範圍,貢獻範圍內的每個位置對它的貢獻值取min,線段樹標記永久化維護即可。

#include using namespace std;

const int n = 400005;

int cnt = 0;

struct item ;

struct graph );

}void sp(int v0,int n) }}

for(int i=1; i<=n; i++)

}void dfs(int p,int x)

void modify(int p,int l,int r,int ql,int qr,int x) else

}int query(int p,int l,int r,int pos) else else

}}} // namespace seg

int chk(int x)

signed main() ;

gs.make(t1,t2,t3,i);

gt.make(t2,t1,t3,i);

}gs.sp(1,n);

gt.sp(n,n);

gs.gen(1,n);

gt.gen(n,1);

int ind = 0;

for(int i=1; gt.fa[i]; i=gt.fa[i])

sid[1]=0;

for(int i=0; iint len=sp.size();

for(int i=1; i<=m; i++)

}for(int i=1; i<=q; i++)

}

HNOI2014 道路堵塞

a國有n座城市,依次標為1到n。同時,在這n座城市間有m條單向道路,每條道路的長度是乙個正整數。現在,a國交通部指定了一條從城市1到城市n的路徑,並且保證這條路徑的長度是所有從城市1到城市n的路徑中最短的。不幸的是,因為從城市1到城市n旅行的人越來越多,這條由交通部指定的路徑經常發生堵塞。現在a國想...

HNOI2014 道路堵塞

a國有n座城市,依次標為1到n。同時,在這n座城市間有m條單向道路,每條道路的長度是乙個正整數。現在,a國交通部指定了一條從城市1到城市n的路徑,並且保證這條路徑的長度是所有從城市1到城市n的路徑中最短的。不幸的是,因為從城市1到城市n旅行的人越來越多,這條由交通部指定的路徑經常發生堵塞。現在a國想...

bzoj3575 Hnoi2014 道路堵塞

一開始看錯題啦!某一條邊不走的最短路相當於1 沿最短路 x y 沿最短路 n,於是 定義t,表示從起點到最短路上序號r有一條長度為l的非最短路。然後用堆維護即可。慎用memset。tle。include include include include include define n 100005 ...