一張有向圖,求去掉任意一條邊後使得最短路最長。求最長的最短路長度以及刪邊的方案數。
題解都說是最短路徑樹,但是實際上這棵樹不用建出來,所以也就是乙個思路而已。
首先找到一條最短路,可以知道能刪的邊肯定在這條路徑上。可以想象一下,就算有多條最短路也不用管,只要找出一條就好了。
然後試著刪掉一條邊,刪邊之後的最短路必然要經過至少一條不在這條路徑上的邊。我們列舉新最短路上的一條新邊,構造出這條最短路徑,那麼在原最短路徑上而不在新最短路徑上的某條邊刪掉時,就有可能會走這條新最短路。
那麼考慮構造這條新最短路。假設列舉到的邊是u->v
,那麼新最短路就是s->u->v->t
,s->u
和v->t
都是最短路樹上的路徑。
然後考慮如何貢獻答案。我們記f[i]
表示原最短路上第i
條邊刪掉之後能得到的最短路長度。那麼只要s->u->v->t
不經過i
,就可以貢獻給i
。我們可以記ner[u][0/1]
表示在正/反最短路樹上,離u
最近的最短路徑上的點,即終點與u
的lca。知道了這個,u->v
貢獻給ner[u][0]->ner[v][1]
這段路徑上的邊就可以了。
因為是線性的,所以線段樹,或者簡單一點,搞個並查集從小到大覆蓋就行。
注意不要用spfa。
圖論好題。
#include
#define pii pair
#define fi first
#define se second
#define mp make_pair
using
namespace std;
const
int n =
2e5+10;
const
int m =
4e5+10;
struct g
void
add_dir
(int _u,
int _v,
int _w)
void
add_undir
(int _u,
int _v,
int _w)
}g;int n, m, dis[2]
[n], pre[n][2
], ner[2]
[n], trs[n]
, pn;
bool inp[n]
, inp1[m]
;struct datadat[m]
;int dn, fa[n]
, fg[n]
, ans1, ans2;
queue<
int> que;
bool inq[n]
;priority_queue que1;
void
dij(
int s,
int d[n])}
for(
int i = g.h[u]
; i; i = g.nxt[i])}
}while
(!que1.
empty()
) que1.
pop();
}void
bfs(
int s,
int d[n]
,int ner[n])}
}}void
get_path()
inp[1]
=1; trs[1]
= pn+1;
bfs(
1, dis[0]
, ner[0]
);bfs(n, dis[1]
, ner[1]
);}bool
cmp(data x, data y)
intfind
(int x)
void
solve()
;}sort
(dat +
1, dat + dn +
1, cmp)
;for
(int i =
1; i <= pn +1;
++ i)
fa[i]
= i;
for(
int i =
1; i <= dn;
++ i)
for(
int j =
find
(dat[i]
.x); j <= dat[i]
.y; j =
find
(j))
ans1 =
0; ans2 =0;
for(
int i =
1; i <= pn;
++ i)
}int
main()
get_path()
;solve()
;if(ans1 == dis[0]
[n])
printf
("%d %d\n"
, ans1, m)
;else
printf
("%d %d\n"
, ans1, ans2)
;return0;
}
最短路徑樹
問題描述 所謂最短路徑樹,就是從s出發,沿著樹上的邊走到任意點i,那麼經過的這些邊的權值和就是s到i的最短路徑。dijkstra演算法或spfa演算法不僅可計算從起點s到各點的最短路徑長度,同時也可得到以s為根的最短路徑樹。方法是在進行鬆弛操作時,如果d i c d j 時,除了更新d j 之外,還...
最短路徑,最短路徑樹和最小生成樹
首先介紹這三個概念,很多人都聽過最短路徑了,但是最短路徑樹卻很少聽過,關於最短路徑樹的介紹也不太多。而最短路徑樹和最小生成樹更是完全不同的兩個概念。最短路徑就是從乙個指定的頂點出發,計算從該頂點出發到其他所有頂點的最短路徑。通常用dijkstra演算法,floyd演算法求解。最短路徑樹spt sho...
SPF(最短路徑樹)演算法
構造一棵樹 a 使n個節點之間的總長最小 樹是乙個在每兩個節點之間僅有一條路徑的圖 在我們給出構造過程中,分支被分成3個集合 被明確分配給構造中的樹的分支 他們將在子樹中 這個分支的隔壁分枝被新增到集合1 剩餘的分支 拋棄或不考慮 節點被分成兩個集合 a 被集合1中的分支連線的節點 b 剩餘的節點 ...