1. 程式人生 > >bzoj 4283 魔法少女伊莉雅 - 最短路

bzoj 4283 魔法少女伊莉雅 - 最短路

display lan 2.3 報告 最短路 def 使用 祖先 lock

題目傳送門

  需要高級權限的快速通道

題目大意

  給定一個$n$個點$m$條邊的帶正權無向圖。要求找一條路徑滿足:

  • 它是一條簡單路徑
  • 它是一條嚴格次短路
  • 對於任何一條可能存在於最短路上的邊,不能包含它的反向邊。

  不存在這條路徑輸出-1。

  神題orz...orz....orz....良心的最短路性質題,涵蓋了大部分最短路徑樹和最短路徑圖上的常用性質。

  直覺是最短路上隨意判一判就好了。然後全WA了,qwq。。

  然後開始講正題。

  將$d\left(u, v \right )$記為點$u$到點$v$的最短路的長度
  記$d_{s}\left(x \right ) = d\left(s, x \right ), d_{t}\left(x \right ) = d\left(x, t \right )$。

  最短路徑圖是$s$到$t$的所有最短路徑的並集。

  舉個例子有助於說明:

  技術分享圖片

  左邊為原圖,右邊為最短路徑圖。

註意 最短路徑圖是一個有向圖。

  這裏將原圖記為$G = (V, E)$,最短路徑圖記為$G* = (V*, E*)$。

最短路徑圖的基本性質I(定義1.1) 對於任意$e \in E*$,若$e = (u, v)$,那麽$d_{s}(u) + w(e) + d_{t}(v) = d(s, t)$。

  顯然最短路徑圖一定是一個DAG。

  然後繼續討論最短路徑圖上的性質。

最短路徑圖的基本性質II(定理1.1) 對於任意$x \in V*$,那麽有$d_{s}(x) + d_{t}(x) = d(s, t)$。

  證明 如果$s = x$,那麽結論顯然成立。

  現在考慮$s \neq x$的情況。暫時記$L = d(s, t)$

  由最短路徑圖的定義可知$d_{s}(x) \geqslant L - d_{t}(x)$。因為$x$不是起點,所以必然存在一個前驅$x‘$。

  根據基本性質I有$d_{s}(x‘) + w(x‘, x) + d_{t}(x) = L$。由$d_{s}(x)$的定義可知$d_{s}(x) \leqslant d_{s}(x‘) + w(x, x‘) = L - d_{t}(x)$。

  所以$d_{s}(x) = L - d_{t}(x)$。

  因此定理得證。

最短路徑圖的基本性質III(推論1.2) 對於$e = (x, y) \in E*$,那麽有$d_{s}(x) + w(x, y) = d_{s}(y)$。

  證明 根據定理1.1有$d_{s}(y) = d(s, t) - d_{t}(y)$。根據定義1.1有$d_{s}(x) + w(x, y) = d(s, t) - d_{t}(y)$。然後定理得證。

最短路徑圖的基本性質IV(推論1.3) 如果最短路徑圖中存在一條$x$到$y$的簡單路徑,那麽$d_{s}(x) + l(P*(x, y)) + d_{t}(y) = L$。其中P*(x, y)表示一條在$G*$上的路徑,l(P*(x, y))表示這條路徑的長度。

  重復使用推論1.2可以得到$d_{s}(x) + l(P*(x, y)) = d_{s}(y)$。然後根據定理1.1易證。詳細證明留給讀者。

最短路徑圖的基本性質V(推論1.4) 最短路徑圖中一條$x$到$y$的簡單路徑,對應原圖中一條$x$到$y$的最短路。

  有了推論1.3就可以使用反證法。詳細證明留給讀者。同時可以推出上面的$ l(P*(x, y)) = d(x, y)$。

定理1.5 若$x, y \in V*$,且滿足$x \neq y, d_{s}(x) \leqslant d_{x}(y)$,那麽在$G*$中$s$到$x$的最短路與$y$到$t$的最短路不相交。

  證明 根據最短路徑圖的定義(定義1.1)可知,$s$到$x$的過程中$d_{s}(x‘)$遞增,$y$到$t$的過程中$d_{s}(y‘)$遞增。又因為$x \neq y, d_{s}(x) \leqslant d_{x}(y)$,所以它們不相交。

  然後來講一些約定吧。

  正向邊:對於一條有向邊$(u, v)$,它在$E*$中,那麽我們稱它為一條正向邊。

  反向邊:對於一條有向邊$(u, v)$,如果$(v, u) \in E*$,那麽我們稱它為一條反向邊。

  內部邊:正向邊和反向邊統稱為內部邊。

  外部邊:在$E$中,但不屬於$E*$的邊。

  現在來明確一下約定路徑的符號。

  $P(u, v)$,表示一條$u$到$v$的路徑。

  $P*(u, v)$,表示一條在$G*$中$u$到$v$的路徑。

  $P(x, y) + Q(y, z)$,表示一條沿著路徑$P$從$x$走到$y$的,然後沿著$Q$,從$y$走到$z$的路徑。

  $P^{-1}(x, y)$,表示沿著路徑$P$的反向邊(不是上面的定義的反向邊),從$y$到$x$的一條路徑。

  $P^{0}(x‘, y‘)$,路徑$P$上,一條$x‘$到$y‘$的子路徑。

  $l(P)$,表示路徑$P$的長度。

  設所求路徑為$S$。

  外部路徑:起點和終點在$G*$中,經過的變都是外部邊的一條簡單路徑。稱起點是這條路徑的拐出點,終點是這條路徑的回歸點

定理2.1 路徑$S$中存在至少1條外部路徑。

  證明 如果不包含外部路徑,那麽路徑$S$中的邊都是正向邊(因為不能走反向邊)。由於$G*$是一個DAG,所以$l(S) = d(s, t)$,不符合題目要求。

定理2.2 路徑$S$的包含一條外部路徑的拐出點為$x$,回歸點為$y$,那麽有$d_{s}(x) \leqslant d_{s}(y)$。

  證明 假設結論不成立,那麽有$d_{s}(x) > d_{s}(y)$$。

  設$S = P(s, x) + Q(x, y) + R(y, t)$。那麽令$U = P*(s, y) + Q^{-1}(x, y) + R*(x, t)$。因為路徑$Q$是一條簡單路徑,P*和R*都是由正向邊組成,根據定理1..5可得P*與R*不相交。所以$U$是一條簡單路徑。

  又因為$U$包含了至少一條外部邊,所以它不是最短路。因此是一條滿足題目要求的路徑。

  又因為$P*(s, y) < P*(s, x) \leqslant P(s, x), R*(x, t) < R*(y, t) \leqslant R(y, t), Q(x, y) = Q^{-1}(x, y)$,所以$l(U) < l(S)$。

  與$S$的最優性矛盾。

定理2.3 路徑$S$恰好包含一條外部路徑。

  證明 假設包含的外部路徑數目不是一條。

  • 如果不包含外部路徑,顯然矛盾。
  • 如果包含超過一條外部路徑,設$S = P*(s, x) + Q(x, y) + R(y, t)$,令$U = P*(s, x) + Q(x, y) + R*(y, t)$,其中$Q(x, y)$是一條外部路徑。
    根據定理1.5易證$U$是一條簡單路徑,根據最短路徑圖的定義有$R*(y, t) < R(y, t)$,因此$l(U) < l(S)$,與$S$的最優性矛盾。

  然後約定$S$的拐出點為$S$包含的外部路徑的拐出點,它的回歸點為它包含的外部路徑的回歸點。

  接下來看一看有關最短路徑樹的性質。

定義3.1 定義一棵以$p$為根的最短路徑樹$T_{p} = (V, E_{T})$是原圖中以$p$為根的一棵有向路徑生成樹。其中一條邊$e(v, u)$滿足$d(u, p) + w(e) = d(v, p)$。

  由於下面只會用到$T_{t}$,因此,以下可能會直接將它簡記$T$。

註意

  1. 這裏的最短路徑樹是一個有向圖。
  2. 所有有向邊都指向根節點。
  3. 一張無向圖的最短路徑圖唯一,但指定點的最短路徑生成樹可能不唯一。

  然後再來定義定義子樹。

定義3.2 在以$p$為根的最短路徑生成樹中:

點$x$的子樹,在$T_{p}$點$x$斷掉點$x$的唯一一條出邊後,剩下的以$x$為根的樹是點$x$的子樹。記為$T_{p}(x)$。

點$x$的真子樹,點$x$的真子樹是$T_{p}(x)$的一個子圖。在$T_{p}(x)$中,存在於點$x$的真子樹的點,當且僅當它到$x$的路徑上不經過除了$x$以外的任何屬於$G*$的點。也就是說一個不是$x$的點,但屬於$G*$,一定不存在於$x$的真子樹中。記為$T*_{p}(x)$。

  真子樹的定義可能不是很好理解(再加上我語文不好),那麽來舉個栗子:

技術分享圖片

  在第三幅圖之後,邊權都被省略。在第四幅圖和第五幅圖中間橙色點標出的是在$G*$中的點。

  下面有一個關於真子樹的很基本的性質。

定理3.1 對於任意$x,y \in G*$,都有$T*(x)\cap T*(y) = \varnothing $。

  根據真子樹的定義易證。

  接下來再來約定一個記號。

  $P_{T}(x, y)$,在樹$T_{t}$中,一條$x$到$y$的路徑。

最短路徑樹中的基本性質(定理3.2 在最短路徑樹$T_{t}$中,任意一個點$x$到其祖先$y$的一條簡單路徑,對應原圖中一條$x$到$y$的最短路。

  證明 易證當$y = t$時結論成立。

  考慮$y \neq t$的情況。

  仍然假設不是最短路。那麽存在一條更優的路徑的從$x$到$y$,然後到$t$的路徑。與$T_{t}$的定義矛盾。

  因此定理得證。

  註意到如果將這條路徑反向,可以對應$y$到$x$在原圖中的一條最短路。

定義3.3 在$T$中,$x$的真祖先是在路徑$P_{T}(x, t)$中,離$x$最近的一個在$G*$中的點。將它記作$prt(x)$。

  換一個說法就是沿著$x$向它的出邊走,直到遇到一個在$G*$中的點。註意,它可能是$x$也可能是$t$。

  設$S$的拐出點為$x$,回歸點為$z$,顯然$x \in T*(x), z \in T*(z)$,根據定理3.1,那麽$T*(x)$和$T*(z)$不存在交集。所以在$S$上必然存在一條外部邊$(w, w‘)$使得$w \in T*(x)$,且$S^{0}(w‘, z)$中的各點均不在$T*(x)$中。有一個很顯然的事實是$prt(w) = x$。

定理3.3 $d_{s}(x) \leqslant d_{s}(prt(w‘))$。

註意 以下證明非常繁瑣,請先喝口水再繼續閱讀。

  證明 仍然假設結論不成立。那麽有$d_{s}(x) > d_{s}(prt(w‘))$。所以$d_{t}(x) < d_{t}(prt(w‘))$。根據定理2.2有$d_{s}(x) <= d_{s}(z)$,因此$d_{s}(prt(w‘)) < d_{s}(z)$,所以$prt(w‘) \neq z$。根據定理3.1,可知,必然存在一條邊$(y, y‘)$使得$y \in T*(prt(w‘))$且$S^{0}(y‘, z)$中的各點均不在$T*(prt(w‘))$。顯然$prt(w‘) = prt(y)$。

技術分享圖片

  令$Q = P*(s, prt(w‘)), R = P_{T}(prt(w‘), y), P = Q + R + S^{0}(y, t)$(見下圖)。

技術分享圖片

  可以證明$R$實際上是在$T*(prt(w‘))$中。假設路徑上經過了其它的在$G*$中的點,那麽可知$prt(y)$不等於$prt(w‘)$,矛盾。

  因為$d_{s}(prt(w‘))< d_{s}(z)$,根據定理1.5可知$Q$不與$S^{0}(z, t)$相交,又因為$R$在$T*(prt(w‘))$中,所以經過的邊都是外部邊,所以$P$中的內部邊不相交。又因為$S^{0}(y‘. z)$是一條外部的簡單路徑,且不在$T*(prt(w‘))$。所以路徑$P$中的外部邊不相交。因此路徑$P$是一條簡單路徑。(註意:這裏的相交指的是存在環,而不是邊與邊存在公共點。)

  又因為$P$包含了至少一條外部邊,所以$P$是一條滿足要求的路徑(除了嚴格次短)。

  因為$S$是所求路徑,所以有:

$l(S) \leqslant l(P)$

$l(S^{0}(s, x)) + l(S^{0}(x, y)) + l(S^{0}(y, t)) \leqslant l(Q) + l(R) + l(S^{0}(y, t))$

$l(S^{0}(s, x)) + l(S^{0}(x, y)) \leqslant l(Q) + l(R)$

$d_{s}(x) + l(S^{0}(x, y)) \leqslant d_{s}(prt(w‘)) + l(R)$(推論1.4)

  又因為$prt(w‘) < d_{s}(x)$,所以$l(S^{0}(x, y)) < l(R)$。

  令$U = S^{0}(x, y)^{-1} + P*(x, t)$。那麽有:

$l(U) = l(S^{0}(x, y)^{-1}) + l(P*(x, y))\\=l(S^{0}(x,y)) + d_{t}(x)\\<l(R) + d_{t}(prt(w‘))\\=l(R^{-1}) + d_{t}(prt(w‘))\\=l(P_{t}(y,t))$

  但是$U$經過了至少一條外部邊,所以有$l(U) > l(P_{T}(y, t)) = d_{t}(y)$。但是剛剛卻推出了與之矛盾的式子。

  所以假設不成立,定理得證:$d_{s}(x) \leqslant(prt(w‘))$。

  這是最後一個定理:

定理3.4 必然存在一個滿足所有條件的路徑S*,滿足

$S* = P_{T}(s, w) + (w, w‘) + P_{T}(w‘, t)$

其中$(w, w‘)$是定理3.3中涉及到的一條邊。

  證明 令$Q = P_{T}(s, w), R = P_{T}(w‘, t)$,根據定理3.1易證$S*$的外部邊不相交,根據定理3.3和定理1.5易證$S*$的內部邊不會相交。又因為$(w, w‘)$一定是一條外部邊。所以$S*$是一條簡單路徑但不是最短路徑。

  因為$S$中包含至少一條非樹邊,然後用反證法易證存在一個$S*$是滿足題目所有要求的路徑(除非原問題不存在解)。

  於是定理3.4創造了無限可能。

  我們只需要枚舉一條非內部邊,非樹邊$e(x, y)$,且滿足$prt(x) \neq prt(y)$且$prt(x) \leqslant prt(y)$,然後用$d_{s}(x) + w(e) + d_{t}(y)$去更新答案即可。

  雖然證明很復雜,但是算法卻異常簡單。

  (終於可以完結撒花了,感覺像是寫了3小時+的論文)

Code

  1 /**
  2  * bzoj
  3  * Problem#4283
  4  * Accepted
  5  * Time: 2720ms
  6  * Memory: 31172k
  7  */ 
  8 #include <bits/stdc++.h>
  9 using namespace std;
 10 typedef bool boolean;
 11 
 12 typedef class Edge {
 13     public:
 14         int ed, nx, w;
 15         
 16         Edge(int ed = 0, int nx = 0, int w = 0):ed(ed), nx(nx), w(w) {         }
 17 }Edge;
 18 
 19 typedef class MapManager {
 20     public:
 21         int ce;
 22         int* h; 
 23         Edge* es;
 24         
 25         MapManager() {            }
 26         MapManager(int n, int m):ce(-1) {
 27             h = new int[(n + 1)];
 28             es = new Edge[(m + 1)];
 29             memset(h, -1, sizeof(int) * (n + 1));
 30         }
 31         
 32         void addEdge(int u, int v, int w) {
 33             es[++ce] = Edge(v, h[u], w);
 34             h[u] = ce;
 35         }
 36         
 37         Edge& operator [] (int p) {
 38             return es[p];
 39         }
 40 }MapManager;
 41 
 42 typedef class Node {
 43     public:
 44         int p;
 45         int dis;
 46         
 47         Node(int p = 0, int dis = 0):p(p), dis(dis) {        }
 48         
 49         boolean operator < (Node b) const {
 50             return dis > b.dis;
 51         }
 52 }Node;
 53 
 54 int n, m;
 55 MapManager g;
 56 MapManager rg;
 57 int *prt;
 58 int *f1, *f2;
 59 boolean *flags;
 60 
 61 inline void init() {
 62     scanf("%d%d", &n, &m);
 63     g = MapManager(n, m << 1);
 64     rg = MapManager(n, m << 1);
 65     for (int i = 1, u, v, w; i <= m; i++) {
 66         scanf("%d%d%d", &u, &v, &w);
 67         g.addEdge(u, v, w);
 68         g.addEdge(v, u, w);
 69     }
 70 }
 71 
 72 priority_queue<Node> que;
 73 
 74 void dijstra(int s, int* &f) {
 75     f = new int[(n + 1)];
 76     memset(f, 0x3f, sizeof(int) * (n + 1));
 77     que.push(Node(s, f[s] = 0));
 78     while (!que.empty()) {
 79         Node e = que.top();
 80         que.pop();
 81         if (e.dis != f[e.p])    continue;
 82         for (int i = g.h[e.p]; ~i; i = g[i].nx) {
 83             Node eu (g[i].ed, f[e.p] + g[i].w);
 84             if (eu.dis < f[eu.p]) {
 85                 f[eu.p] = eu.dis;
 86                 que.push(eu);
 87             }
 88         }
 89     }
 90 }
 91 
 92 void dfs(int p) {
 93     for (int i = rg.h[p]; ~i; i = rg[i].nx) {
 94         int e = rg[i].ed;
 95         if (f1[e] + f2[e] == f1[n])
 96             prt[e] = e;
 97         else
 98             prt[e] = prt[p];
 99         dfs(e);
100     }
101 }
102 
103 int ans = (1 << 30);
104 inline void solve() {
105     dijstra(1, f1), dijstra(n, f2);
106     prt = new int[(n + 1)];
107     flags = new boolean[(m * 2 + 1)];
108     memset(prt, 0, sizeof(int) * (n + 1));
109     for (int i = 1, e; i <= n; i++) {
110         for (int j = g.h[i]; ~j; j = g[j].nx) {
111             e = g[j].ed;
112             if (f2[e] + g[j].w == f2[i]) {
113                 rg.addEdge(e, i, 0);
114                 flags[j] = true;
115                 break;
116             }
117         }
118     }
119     prt[n] = n;
120     dfs(n);
121     for (int i = 1, e; i <= n; i++) {
122         for (int j = g.h[i]; ~j; j = g[j].nx) {
123             e = g[j].ed;
124             if (!flags[j]) {
125                 if (f1[i] + g[j].w + f2[e] == f1[n] || f2[i] + g[j].w + f1[e] == f1[n])    continue;
126                 if (prt[i] != prt[e] && f1[prt[i]] <= f1[prt[e]])
127                     ans = min(ans, f1[i] + g[j].w + f2[e]);
128             }
129         }
130     }
131     if (ans == (1 << 30))
132         puts("-1");
133     else
134         printf("%d", ans);
135 }
136 
137 int main() {
138     init();
139     solve();
140     return 0;
141 }

寫在後面的鬼扯

   由於這篇博客寫了3個小時+,所以不能保證證明過程全是正確的,有問題請及時指出。

參考文獻

  《excape解題報告》 by Unknown

  很抱歉,我真的不知道它的作者是誰。只是當作考試的題解發下來的資料。

特別鳴謝

  感謝YYR提供的資料以及許多騙分做法

  感謝Doggu和我一起研究這個問題

  感謝ZJC幫助我調試程序

(轉載請註明出處:http://www.cnblogs.com/yyf0309/p/8563071.html)

bzoj 4283 魔法少女伊莉雅 - 最短路