1. 程式人生 > >簡單圖論:遍歷所有最短路徑

簡單圖論:遍歷所有最短路徑

今天遇到了兩道要求遍歷所有最短路徑的題,我一直做不對的原因竟是我把無向圖當成了有向圖,鬱悶的要死。

解決遍歷所有最短路徑,其實思路很簡單,首先通過經典演算法[各種演算法,Dijkstra,bellman,floyd]求出最短路徑的長度,然後就只能DFS來找尋起始點、終點一樣,長度為最短路徑長度的路徑即可,在DFS中可以使用Path[]陣列來儲存路徑。

DFS時注意要剪枝,路徑上已經走過的點不要重複走,可以用Visited[]來儲存。

這裡要注意的是,如果邊的權均為正,那麼DFS的效率還是挺高的,可以在大於最短路時直接剪掉

如果邊權存在負值,DFS就剪不了那麼多枝了...

基本的演算法如下:

初始時使用DFS(起點,0)即可,其中D表示的是終點,可以作為全域性變數,start表示起始點,整個圖都使用二維陣列來存的,不過轉成表演算法也差不多。

ansdis表示的是之前求出來的最短路,而shortnum統計最短路徑的條數。

void DFS(int start, int dis)
{
     int i,j;
     if(dis>ansdist) return;  //帶負權則不可剪枝
     for(i=0;i<N;i++)
     {
         if(!Visited[i] && i!=start && Graph[start][i]!=Infinity)
         {
             if(dis + Graph[start][i] > ansdist) continue; //帶負權則不可剪枝
             else if(i==D && dis+Graph[start][i]==ansdist)
             {
                 Path[start]=i;
                 shortnum++;
                 //此時就可以把Path[]路徑列印或儲存
             }
             else
             {
                 Visited[start]=true;
                 int temp=Path[start];
                 Path[start]=i;
                 DFS(i,dis+Graph[start][i]);
                 Visited[start]=false;
                 Path[start]=temp;
             }
         }
     }
}