HDU-3790最短路徑問題,第十遍終於過了~
阿新 • • 發佈:2019-01-25
最短路徑問題
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)-> Link <-
這道題題意很簡單,n個景點,m條路(雙向),每條路有一個距離和花費,然後給定起點和終點,求起點到終點的最短距離及花費,如果最短路徑有多條,輸出花費最小的那條
基於資料範圍不大,除了弗洛伊德其他的最短路解法都是可以的,博主習慣用迪傑斯特拉,所以本文介紹dij的解法;
思路;最短路的變形,以前都是直接求出起點到終點的最短路,而這裡就是加上了一個花費問題,所以我們在用dij演算法時注意如果路徑相同的時候取花費小的即可,否則,只要路徑小,兩個變數都無條件變;
坑點:樣例水過,就是不知道跪在哪,看了討論區才知道有重邊的情況,所以在輸入的時候需要注意如果兩個點路徑有多條相同的取花費小的,否則取路徑最短的那條不用管花費;也就是說,不管在輸入或者輸出的時候都要以路徑為前提,一定要的是最短的,如果最短的有多條再取花費小的;
#include<bits/stdc++.h> using namespace std; const int INF=0x3f3f3f; const int N=1000+10; struct node { int p,d; } a[N][N];輸入的; struct node1 { int d,p; } v[N];起點到i點的最短路徑及花費; int vis[N]; int main() { int n,m,xx,yy,i,j,d,p; while(~scanf("%d%d",&n,&m)&&n&&m) { for(i=1; i<=n; i++) for(j=1; j<=n; j++) a[i][j].d=a[i][j].p=(i==j?0:INF); memset(vis,0,sizeof(vis)); for(i=1; i<=m; i++) { scanf("%d%d%d%d",&xx,&yy,&d,&p); if(d<a[xx][yy].d)//如果最短路只有一條,兩個變數都無條件改變; { a[xx][yy].d=a[yy][xx].d=d; a[xx][yy].p=a[yy][xx].p=p; } else if(d==a[xx][yy].d)//有多條相同的時候才取花費最小的; { a[xx][yy].p=a[yy][xx].p=min(p,a[xx][yy].p); } } scanf("%d%d",&xx,&yy); for(i=1; i<=n; i++) v[i].d=v[i].p=i==xx?0:INF; for(i=1; i<=n; i++) { int x,mm=INF; for(j=1; j<=n; j++) if(!vis[j]&&v[j].d<=mm) mm=v[x=j].d; vis[x]=1; for(j=1; j<=n; j++) { if(v[j].d>a[x][j].d+v[x].d) { v[j].d=a[x][j].d+v[x].d; v[j].p=a[x][j].p+v[x].p; } else if(v[j].d==a[x][j].d+v[x].d)//如果最短路徑有多條,取花費最小的; v[j].p=min(v[j].p,a[x][j].p+v[x].p); } } printf("%d %d\n",v[yy].d,v[yy].p); } return 0; }