對不起對不起,辣雞蒟蒻又來用核彈打蚊子了
完全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 ...