Question:
Given a directed graph, findRound-tripShortest Path and. This graph has a property: any ring will go through the source point.
The number of nodes in the figure ranges from 0 ~ 100 million;
Analysis:
First, we can use the Dijkstra algorithm to solve the shortest distance from the source point to the other points. This completes half of the work.
So how can we solve the shortest path from each point to the source point?
1. We can cyclically perform n-1 times, calculate the shortest path from point I to other points, and obtain the shortest path from point I to the source point. In this way, we can use the shortest path from other points to the source point.
Obviously, the above method has a lot of redundancy, and the value range for the question is: 0 ~ 100, will definitely time out. If you don't believe it, try it.
According to the practice of appeal method, the code for timeout is as follows:
#include<cstdio>#include<string.h>#include<iostream>#include<vector>#include<queue>using namespace std;#define maxn 1000000#define inf 0x3f3f3f3ftypedef pair<int,int> P;struct edge{int t;int c;edge(){t=0,c=0;}edge(int tt,int cc){t=tt,c=cc;}};int dist[maxn];vector<edge> map[maxn];void dijkstra(int s,int n){priority_queue<P,vector<P>,greater<P> > Q;for(int i=1;i<=n;i++)dist[i]=inf;dist[s]=0;bool visited[maxn];memset(visited ,0,sizeof(visited));Q.push(P(0,s));while(!Q.empty()){int v=Q.top().second;Q.pop();if(visited[v]) continue;visited[v]=true;for(int i=0;i<map[v].size();i++){edge e=map[v][i];if(dist[e.t]>dist[v]+e.c){dist[e.t]=dist[v]+e.c;Q.push(P(dist[e.t],e.t));}}}}void init(int n){for(int i=0;i<=n;i++){map[i].clear();}}int main(){//freopen("in.txt","r",stdin);int cases;scanf("%d",&cases);for(int t=1;t<=cases;t++){int n,m;scanf("%d %d",&n,&m);init(n);while(m--){int a,b,c;scanf("%d %d %d",&a,&b,&c);map[a].push_back(edge(b,c));}dijkstra(1,n);int sum=0;for(int i=1;i<=n;i++)sum+=dist[i];for(int i=2;i<=n;i++){dijkstra(i,n);sum+=dist[1];}printf("%d\n",sum);}}
2. A good method has been found through answers from others.
First, we need to construct the reverse graph of the source image.
The source image is a directed graph. The reverse graph is based on the source image. The Source Vertex of the edge of the source image is the destination vertex of the reverse graph, and the destination vertex of the edge of the source image is the Source Vertex of the reverse graph.
In short, all the direction of the edge of the source image is reversed to form an inverse graph.
After constructing the reverse graph, we will apply the Dijkstra algorithm to the reverse graph. The source point is 1.
Next, we get the shortest distance from the source point to the other points. Note that our graph is the reverse graph of the source image, so:
What we get isThe shortest distance from other nodes to the source node.
3. Is the adjacent table a two-dimensional matrix?
We also need to pay attention to an important question: how to store edge information?
According to the data range in the question 0-100 W, we cannot open up such a large two-dimensional matrix, so we must use the adjacent table for storage.
Here we use vector implementation.
Source code:
#include<cstdio>#include<string.h>#include<iostream>#include<vector>#include<queue>using namespace std;#define maxn 1000001#define inf 0x3f3f3f3ftypedef pair<int,int> P;struct edge{int f;int t;int c;edge(){f=0,t=0,c=0;}edge(int ff,int tt,int cc){f=ff,t=tt,c=cc;}};int dist[maxn];vector<edge> map[maxn];edge edges[maxn];void dijkstra(int s,int n){priority_queue<P,vector<P>,greater<P> > Q;for(int i=1;i<=n;i++)dist[i]=inf;dist[s]=0;bool visited[maxn];memset(visited ,0,sizeof(visited));Q.push(P(0,s));while(!Q.empty()){int v=Q.top().second;Q.pop();if(visited[v]) continue;visited[v]=true;for(int i=0;i<map[v].size();i++){edge e=map[v][i];if(dist[e.t]>dist[v]+e.c){dist[e.t]=dist[v]+e.c;Q.push(P(dist[e.t],e.t));}}}}void init(int n){for(int i=0;i<=n;i++){map[i].clear();}}int main(){//freopen("in.txt","r",stdin);int cases;scanf("%d",&cases);for(int t=1;t<=cases;t++){int n,m;scanf("%d %d",&n,&m);init(n);for(int i=1;i<=m;i++){int a,b,c;scanf("%d %d %d",&a,&b,&c);edges[i]=edge(a,b,c);map[a].push_back(edge(a,b,c));}dijkstra(1,n);long long int sum=0;for(int i=1;i<=n;i++)sum+=dist[i];init(n);for(int i=1;i<=m;i++){edge tmp=edges[i];map[tmp.t].push_back(edge(tmp.t,tmp.f,tmp.c));}dijkstra(1,n);for(int i=1;i<=n;i++)sum+=dist[i];printf("%lld\n",sum);}}
Poj-1511 invitation cards (Dijkstra deformation question)