2011-08-26 40 views
24

Tìm đường đi ngắn nhất giữa hai điểm trong biểu đồ là câu hỏi thuật toán cổ điển với nhiều câu trả lời hay (Dijkstra's algorithm, Bellman-Ford, v.v.) Câu hỏi của tôi là liệu có một thuật toán hiệu quả, được chỉ định, biểu đồ có trọng số, một cặp các nút s và t, và một giá trị k, tìm đường k-ngắn nhất giữa s và t. Trong trường hợp có nhiều đường dẫn có cùng độ dài mà tất cả đều buộc cho kth-shortest, thì tốt nhất cho thuật toán trả về bất kỳ giá trị nào trong số chúng.Tìm đường dẫn k-ngắn nhất?

Tôi nghi ngờ rằng thuật toán này có thể có thể được thực hiện trong thời gian đa thức, mặc dù tôi biết rằng có thể có sự giảm từ longest path problem mà sẽ làm cho nó NP-cứng.

Có ai biết thuật toán như vậy hay giảm xuống cho thấy rằng đó là NP-hard không?

+0

http: //www.springerlink .com/content/pl0054nt2d0d2u3t/ –

+0

Bạn gần như chắc chắn đề cập đến vấn đề đường dẫn ngắn nhất k-th, nhưng nếu bạn quan tâm đến các đường phân tách cạnh, bạn có thể tìm chúng bằng thuật toán Edmonds-Karp: http: // www .mat.uc.pt/~ eqvm/OPP/KSPP/KSPP.html – IVlad

+4

Chỉ cần thông tin: Thuật toán của Yen là khi bạn chỉ xem xét các đường dẫn đơn giản, trong khi Thuật toán của Eppstein là trường hợp đường dẫn không đơn giản được cho phép (ví dụ: đường dẫn được phép truy cập lại cùng một nút nhiều lần). Tiếp theo, nếu bạn muốn đường dẫn ngắn nhất * nghiêm ngặt * (tôi biết bạn đã chỉ ra điều ngược lại), phiên bản không đơn giản nằm trong P, phiên bản không bị đơn giản là P (Krasikov-Noble/Zhang-Nagamochi), và phiên bản đạo diễn đơn giản là NP-hard (Lalgudi-Papaefthymiou). Ngoài ra, đối với những gì nó có giá trị, tôi đã không nhìn thấy bất kỳ mô tả rất tốt về thuật toán của Yên, nhưng tôi muốn một! – daveagp

Trả lời

10

Bạn đang tìm thuật toán của Yen để tìm kiếm các đường đi ngắn nhất K. Con đường ngắn nhất k sau đó sẽ là con đường cuối cùng trong tập hợp đó.

Dưới đây là implementation thuật toán của Yen.

Và đây là số original paper mô tả.

+0

Xin lỗi tôi không có thời gian để mô tả nó và viết nó lên trong bài đăng này ngay bây giờ. Nhưng tôi có thể làm điều đó sau nếu bạn không thể truy cập bài báo. – tskuzzy

-1

Mặc dù câu hỏi có câu trả lời được chấp nhận hợp lệ, câu trả lời này giải quyết vấn đề triển khai bằng cách cung cấp mã làm việc mẫu. Tìm mã có giá trị thứ k con đường ngắn nhất ở đây:

// Thời gian phức tạp: O (V k (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; 
} 
Các vấn đề liên quan