無向圖最短路徑問題
阿新 • • 發佈:2018-11-24
給你n個點,m條無向邊,每條邊都有長度d和花費p,給你起點s終點t,要求輸出起點到終點的最短距離及其花費,如果最短距離有多條路線,則輸出花費最少的。
Input
輸入n,m,點的編號是1~n,然後是m行,每行4個數 a,b,d,p,表示a和b之間有一條邊,且其長度為d,花費為p。最後一行是兩個數 s,t;起點s,終點。n和m為0時輸入結束。
(1<n<=1000, 0<m<100000, s != t)
Output
輸出 一行有兩個數, 最短距離及其花費。
Sample Input
3 2
1 2 5 6
2 3 4 5
1 3
0 0
Sample Output
9 11
求最短路徑問題,即從一點到另外一點的最短路徑,Dijkstra演算法即可解決,時間複雜度O(n^2)
在最短路都多條的情況下,求最少花費,加個判斷條件即可
for(int i=1;i<=n;i++) { if(dis[i]==dis[u]+g[u][i]) { if(c[i]>c[u]+cost[u][i] ) c[i]=c[u]+cost[u][i]; } else if(dis[i]>dis[u]+g[u][i]) { dis[i]=dis[u]+g[u][i]; c[i]=c[u]+cost[u][i]; } }
程式碼如下:
//Dijkstra演算法 臨接矩陣 #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=1005; int g[N][N]; //存圖 N->N 的距離 int cost[N][N]; //存圖N->N 的花費 int c[N]; //存最小花費 int dis[N]; //存最小距離 int vis[N],n,m; //標記改點是否已經走過 int t1,t2; #define Inf 0x3f3f3f3f void Init() { memset(g,Inf,sizeof(g)); memset(cost,Inf,sizeof(cost)); for(int i=1;i<=n;i++) { g[i][i]=0; cost[i][i]=0; } } void GetMap() { for(int i=0;i<m;i++) { int u,v,w,p; scanf("%d%d%d%d",&u,&v,&w,&p); if(g[u][v]>w) { g[u][v]=g[v][u]=w; cost[u][v]=cost[v][u]=p; } } } void Dijkstra() { memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++) { dis[i]=g[t1][i]; c[i]=cost[t1][i]; } vis[t1]=1; int u; for(int k=1;k<n;k++) { int minn=Inf; for(int i=1;i<=n;i++) { if(!vis[i]&&dis[i]<minn) { minn=dis[i]; u=i; } } vis[u]=1; for(int i=1;i<=n;i++) { if(dis[i]==dis[u]+g[u][i]) { if(c[i]>c[u]+cost[u][i] ) c[i]=c[u]+cost[u][i]; } else if(dis[i]>dis[u]+g[u][i]) { dis[i]=dis[u]+g[u][i]; c[i]=c[u]+cost[u][i]; } } } } int main() { while(scanf("%d%d",&n,&m)) { if(n==0 && m==0) break; Init(); GetMap(); scanf("%d%d",&t1,&t2); Dijkstra(); cout<<dis[t2]-dis[t1]<<" "<<c[t2]-c[t1]<<endl; } return 0; }