图中所有节点到特定节点的最短路径成本

Posted

技术标签:

【中文标题】图中所有节点到特定节点的最短路径成本【英文标题】:Shortest path cost from all nodes to a particular node in a graph 【发布时间】:2016-10-31 10:35:22 【问题描述】:

我正在做一个问题,我必须计算从一个特定节点(起始节点)到 有向 图中的所有其余节点然后返回的总成本这些节点到起始节点。 现在对于问题的第一部分,即从开始到其余节点,我已经应用了 dijkstra 算法,但对于第二部分,我想将每个节点作为源循环并为每个节点使用 dijkstra。但是,如果我没记错的话,dijkstra 会计算从一个源节点到其余节点的路径成本,在这种情况下会导致大量开销。对于问题的第二部分,我只需要从所有节点到一个特定节点的最短路径。

这是我一直在做的(忽略getchar,那只是为了加快输入)。

#include<set>
#include<stdio.h>
#include<vector>
#include<limits.h>
#include<cstdio>
using namespace std;

#define mp make_pair
#define ft first
#define sd second
#define gc getchar

vector< pair<int,int> > g[101000];
int n,m,sum,i,j,k,t,x,y,z;
vector<int> dist;
vector <int> vis;

void scanint(int &x)

    register int c = gc();
    x=0;
    for(;(c<48||c>57);c=gc());
    for(;c>47&&c<58;c=gc())
    
        x=(x<<1)+(x<<3)+c-48;
    

void dijkstra(int source)

    dist.clear();
    int i,j,k;
    for(i=0;i<n;i++)
    
        dist.push_back(INT_MAX);
        vis.push_back(0);
    
    dist[source] = 0;
    set< pair<int,int> > s; // pair is dist, node_number
    set< pair<int,int> >::iterator it;

    for(i=0;i<n;i++)
        s.insert(mp(dist[i],i));

    while(!s.empty())
    
        it = s.begin();
        pair<int,int> temp = *it;
        s.erase(temp); // remove minimum val node
        int cur = temp.sd;
        int val = temp.ft;

        if(val == INT_MAX)
            return;
        for(i=0;i<g[cur].size();i++)
        
            int nb = g[cur][i].ft;
            if(!vis[nb] && dist[nb] > val + g[cur][i].sd)
            
                s.erase(mp(dist[nb],nb)); // erase old val
                dist[nb] = val + g[cur][i].sd;
                s.insert(mp(dist[nb],nb));
            
        
    
    s.clear();


int main()

   // std::ios::sync_with_stdio(false);
    scanint(t);
    for(int r=0;r<t;r++)
    
        dist.clear();
        vis.clear();


        scanint(n);
        scanint(m);
        for(i=0;i<m;i++)
            g[i].clear();

        for(i=0;i<m;i++)
        
            scanint(x);
            scanint(y);
            scanint(z);
            x--;    y--;
            g[x].push_back(mp(y,z));

        
        dijkstra(0);
        sum=0;
        for(int i=0;i<n;i++)
        sum=sum+dist[i];
        for(int i=0;i<n;i++)
        
          dijkstra(i);
          sum=sum+dist[0];
        
        printf("%d\n",sum);
        g[x].clear();
        for(int i=0;i<n;i++)
        
            dist[i]=INT_MAX;
        
    
    return 0;

【问题讨论】:

在无向图中 minPath(a,b)=minPath(b,a)。因此,您可以将从一个节点转移到其他节点的成本翻倍 @AlexanderAnikin 是单向的不是无向的,不能用同一个路径回溯。 @AlexanderAnikin:这取决于您所说的“单向”是什么意思。我猜它的意思是“导演”。在这种情况下,您的陈述是错误的。可能没有从“b”到“a”的路径。 老实说,我不知道 unidirected 是什么意思——它不规范。如果它是有向图,我的评论与案例无关,如果它是“无向”或模拟无向(当你制作两条有向边而不是一条无向边时),评论是有效的。 将单向更新为定向 【参考方案1】:

您应该使用产生shortest-path tree 的寻路算法。 Dijkstra 算法和 Bellman-Ford 算法都可以用于此。他们中的哪一个会表现更好将取决于density of your graph。对于稀疏图,Dijkstra 算法会更快。

然后您可以执行以下操作:

    从源节点计算最短路径树。您现在将拥有从源节点到所有目的地的路径。 反转图中所有边的方向,并再次从源节点计算最短路径树。这棵树现在将包含从目标节点到原始源节点的最短路径。

【讨论】:

以上是关于图中所有节点到特定节点的最短路径成本的主要内容,如果未能解决你的问题,请参考以下文章

具有动态边缘成本的最短路径(算法)

求图中任意两点之间最短路径有啥算法?

图中的最短路径查询

Floyd-Warshall求图中任意两点的最短路径

最短路径——Floyd算法

SQL - postgres - 图中的最短路径 - 递归