您的位置:首页 > 其它

多源最短路径Floyd、Floyd求最小环【模板】

2015-05-13 20:55 411 查看
Floyd算法:用来找出每对点之间的最短距离。图可以是无向图,也可以是有向图,边权可为正,也可以为负,唯一要求是不能有负环。 

1.初始化:将Map[][]中的数据复制到Dist[][]中作为每对顶点之间的最短路径的初值,Pre[i][j] = i 表示 i 到 j 路径中 j 的前一节点。 

2. k 从 1 到 N 循环 N 次,每次循环中,枚举图中不同的两点 i,j,如果Dist[i][j] > Dist[i][k] + Dist[k][j],则更新Dist[i][j] = Dist[i][k] + Dist[k][j],更新Pre[i][j] = Pre[k][j]。 

只要图中不存在负环就可以得出正确的答案,关于Floyd算法对负环的判定,参考下边Floyd求最小环。
<code class="hljs markdown has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">const int MAXN = 110;
const int INF = 0xffffff0;

int Map[<span class="hljs-link_label" style="box-sizing: border-box;">MAXN</span>][<span class="hljs-link_reference" style="box-sizing: border-box;">MAXN</span>], Dist[<span class="hljs-link_label" style="box-sizing: border-box;">MAXN</span>][<span class="hljs-link_reference" style="box-sizing: border-box;">MAXN</span>],Pre[<span class="hljs-link_label" style="box-sizing: border-box;">MAXN</span>][<span class="hljs-link_reference" style="box-sizing: border-box;">MAXN</span>];
//Pre[<span class="hljs-link_label" style="box-sizing: border-box;">i</span>][<span class="hljs-link_reference" style="box-sizing: border-box;">j</span>] = i表示i到j路径中j的前一节点
void Floyd(int N)
{   //初始化
<span class="hljs-code" style="box-sizing: border-box;">    for(int i = 1; i <= N; ++i)</span>
<span class="hljs-code" style="box-sizing: border-box;">    {</span>
<span class="hljs-code" style="box-sizing: border-box;">        for(int j = 1; j <= N; ++j)</span>
<span class="hljs-code" style="box-sizing: border-box;">        {</span>
<span class="hljs-code" style="box-sizing: border-box;">            Dist[i][j] = Map[i][j];</span>
<span class="hljs-code" style="box-sizing: border-box;">            Pre[i][j] = i;</span>
<span class="hljs-code" style="box-sizing: border-box;">        }</span>

<span class="hljs-code" style="box-sizing: border-box;">    }</span>
<span class="hljs-code" style="box-sizing: border-box;">    for(int k = 1; k <= N; ++k)</span>
<span class="hljs-code" style="box-sizing: border-box;">    {</span>
<span class="hljs-code" style="box-sizing: border-box;">        for(int i = 1; i <= N; ++i)</span>
<span class="hljs-code" style="box-sizing: border-box;">        {</span>
<span class="hljs-code" style="box-sizing: border-box;">            for(int j = 1; j <= N; ++j)</span>
<span class="hljs-code" style="box-sizing: border-box;">            {   //如果Dist[i][j] > Dist[i][k] + Dist[k][j],则更新</span>
<span class="hljs-code" style="box-sizing: border-box;">                if(Dist[i][k] != INF && Dist[k][j] != INF && Dist[i][k] + Dist[k][j] < Dist[i][j])</span>
<span class="hljs-code" style="box-sizing: border-box;">                {</span>
<span class="hljs-code" style="box-sizing: border-box;">                    Dist[i][j] = Dist[i][k] + Dist[k][j];</span>
<span class="hljs-code" style="box-sizing: border-box;">                    Pre[i][j] = Pre[k][j];  //更新Pre[i][j]</span>
<span class="hljs-code" style="box-sizing: border-box;">                }    </span>
<span class="hljs-code" style="box-sizing: border-box;">            }</span>
<span class="hljs-code" style="box-sizing: border-box;">        }</span>
<span class="hljs-code" style="box-sizing: border-box;">    }</span>
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li></ul>


如果求点u到点v能达到的最长边尽可能短的路径上最长边为多少,将循环内部改为如下代码:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> tMax;   <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//这里边求的是能达到的路径上最长边最小为多少  </span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(Dist[i][k] > Dist[k][j])
tMax = Dist[i][k];
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>
tMax = Dist[k][j];
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(Dist[i][j] > tMax)
Dist[i][j] = tMax;  </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>


Floyd求最小环 

不能在Map[][]数组上直接计算,因为判断过程中用到了Map[][]原始值。
<code class="hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> MAXN = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">110</span>;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> INF = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xffffff0</span>;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> temp,Map[MAXN][MAXN],Dist[MAXN][MAXN],pre[MAXN][MAXN],ans[MAXN*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>];

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> Solve(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> j,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> k)
{
temp = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;   <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//回溯,存储最小环</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span>(i != j)
{
ans[temp++] = j;
j = pre[i][j];
}
ans[temp++] = i;
ans[temp++] = k;
}
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> Floyd(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> N)
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>; i <= N; ++i)
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> j = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>; j <= N; ++j)
{
Dist[i][j] = Map[i][j];
pre[i][j] = i;
}
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> MinCircle = INF;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//最小环</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> k = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>; k <= N; ++k)
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>; i <= N; ++i)
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> j = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>; j <= N; ++j)
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(i != j && Dist[i][j] != INF && Map[i][k] != INF && Map[k][j] != INF
&& Dist[i][j] + Map[i][k] + Map[k][j] < MinCircle)
{
MinCircle = min(MinCircle, Dist[i][j] + Map[i][k] + Map[k][j]);
Solve(i,j,k);   <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//回溯存储最小环</span>
}
}
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>; i <= N; ++i)
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> j = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>; j <= N; ++j)
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(Dist[i][k] != INF && Dist[k][j] != INF &&
Dist[i][k] + Dist[k][j] < Dist[i][j])
{
Dist[i][j] = Dist[i][k] + Dist[k][j];
pre[i][j] = pre[k][j];  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//记录点i到点j的路径上,j前边的点</span>
}
}
}
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(MinCircle == INF)    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//不存在环</span>
{
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"No solution.\n"</span>);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
}
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果求出最小环为负的,原图必定存在负环</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;i < temp; ++i)    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//输出最小环</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(i != temp-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"%d "</span>,ans[i]);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"%d\n"</span>,ans[i]);
}</code>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: