查找圖中兩點之間的最短路徑是一個經典算法問題,其中有很多很好的答案(Dijkstra's algorithm,Bellman-Ford等)。我的問題是,節點s和t以及值k,找到s和t之間的第k個最短路徑。如果有多條相同長度的路徑都是第k個最短的路徑,那麼算法返回它們中的任何一個都可以。找到第k個最短路徑?
我懷疑這個算法可能可以在多項式時間完成,但我知道可能會減少從longest path problem,這將使其NP-hard。
有沒有人知道這樣的算法,或減少,表明它是NP難?
查找圖中兩點之間的最短路徑是一個經典算法問題,其中有很多很好的答案(Dijkstra's algorithm,Bellman-Ford等)。我的問題是,節點s和t以及值k,找到s和t之間的第k個最短路徑。如果有多條相同長度的路徑都是第k個最短的路徑,那麼算法返回它們中的任何一個都可以。找到第k個最短路徑?
我懷疑這個算法可能可以在多項式時間完成,但我知道可能會減少從longest path problem,這將使其NP-hard。
有沒有人知道這樣的算法,或減少,表明它是NP難?
最好的(並且基本上是最優的)算法歸結於Eppstein。
對不起,我沒有時間描述它,現在寫在這篇文章中。但如果您無法訪問該文件,我可以稍後再做。 – tskuzzy
儘管該問題有一個有效的接受答案,但該答案通過提供示例工作代碼來解決實施問題。查找第k最短路徑此處的有效代碼:
//時間複雜度:O(V ķ(V * logV + E))
using namespace std;
typedef long long int ll;
typedef short int i16;
typedef unsigned long long int u64;
typedef unsigned int u32;
typedef unsigned short int u16;
typedef unsigned char u8;
const int N = 128;
struct edge
{
int to,w;
edge(){}
edge(int a, int b)
{
to=a;
w=b;
}
};
struct el
{
int vertex,cost;
el(){}
el(int a, int b)
{
vertex=a;
cost=b;
}
bool operator<(const el &a) const
{
return cost>a.cost;
}
};
priority_queue <el> pq;
vector <edge> v[N];
vector <int> dist[N];
int n,m,q;
void input()
{
int i,a,b,c;
for(i=0;i<N;i++)
v[i].clear();
for(i=1;i<=m;i++)
{
scanf("%d %d %d", &a, &b, &c);
a++;
b++;
v[a].push_back(edge(b,c));
v[b].push_back(edge(a,c));
}
}
void Dijkstra(int starting_node, int ending_node)
{
int i,current_distance;
el curr;
for(i=0;i<N;i++)
dist[i].clear();
while(!pq.empty())
pq.pop();
pq.push(el(starting_node,0));
while(!pq.empty())
{
curr=pq.top();
pq.pop();
if(dist[curr.vertex].size()==0)
dist[curr.vertex].push_back(curr.cost);
else if(dist[curr.vertex].back()!=curr.cost)
dist[curr.vertex].push_back(curr.cost);
if(dist[curr.vertex].size()>2)
continue;
for(i=0;i<v[curr.vertex].size();i++)
{
if(dist[v[curr.vertex][i].to].size()==2)
continue;
current_distance=v[curr.vertex][i].w+curr.cost;
pq.push(el(v[curr.vertex][i].to,current_distance));
}
}
if(dist[ending_node].size()<2)
printf("?\n");
else
printf("%d\n", dist[ending_node][1]);
}
void solve()
{
int i,a,b;
scanf("%d", &q);
for(i=1;i<=q;i++)
{
scanf("%d %d", &a, &b);
a++;
b++;
Dijkstra(a,b);
}
}
int main()
{
int i;
for(i=1;scanf("%d %d", &n, &m)!=EOF;i++)
{
input();
printf("Set #%d\n", i);
solve();
}
return 0;
}
HTTP://www.springerlink .com/content/pl0054nt2d0d2u3t/ –
你幾乎肯定是指一般的第k個最短路徑問題,但是如果你對邊緣不相交的路徑感興趣,你可以使用Edmonds-Karp算法找到它們:http:// www .mat.uc.pt /〜eqvm/OPP/KSPP/KSPP.html – IVlad
僅供參考:Yen的算法適用於只考慮簡單路徑的情況,而Eppstein算法適用於允許非簡單路徑的情況(例如,允許路徑多次重新訪問同一節點)。切線方向,如果你想*嚴格*第二條最短路徑(我知道你說的是相反的),非簡單版本在P中,簡單的無向版本在P中(Krasikov-Noble/Zhang-Nagamochi),而簡單定向版本是NP-hard(Lalgudi-Papaefthymiou)。另外,對於它的價值,我還沒有看到Yen的算法有很好的描述,但我想要一個! – daveagp