标签:
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 9602 Accepted Submission(s): 3111
题解:最短路 注意有重边,这里介绍一种用链表存 的时候可以不用考虑重边,方法就是将所有的边都标记为未访问,然后将其他边的值标记成INF,将开始那条边的值标记成0 ,然后加入n边,每次更新的时候就不用考虑重边了。
这个题因为数据量特别的大,dijk的算法本身是O (n^2)的,查询的时候调用n次dijk所以总共是O(n^3),所以最后会超时,可以逆向思维,因为终点是已知的所以从终点开始dijk一次后找到所有的已知起点中距离最小的点就可以了。
注意这个题中是有向边。
下面是代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define N 2000 7 #define M 400000 8 #define INF 0x1fffffff 9 struct Edge{ 10 int to ; 11 int v; 12 int next; 13 }edge[M]; 14 int head[N]; 15 int Ecnt; 16 void init() 17 { 18 Ecnt = 0; 19 memset(head,-1,sizeof(head)); 20 } 21 void add(int from , int to ,int v) 22 { 23 edge[Ecnt].to = to; 24 edge[Ecnt].v = v; 25 edge[Ecnt].next = head[from]; 26 head[from] = Ecnt++; 27 } 28 int dist[N]; 29 bool p[N]; 30 void dijk(int s, int n) 31 { 32 int i , j , k ; 33 for(i = 0 ;i <= n ;i++) 34 { 35 p[i] = false; 36 dist[i] = INF; 37 } 38 //p[s] = true; 39 dist[s] = 0; 40 41 for( i = 0; i < n ; i++) 42 { 43 int Min = INF ; 44 int k = 0 ; 45 for( j = 1 ; j <= n ; j++) 46 { 47 if(!p[j]&&dist[j]<Min) 48 { 49 Min = dist[j]; 50 k = j; 51 } 52 } 53 if(Min == INF ) return ; 54 p[k] = true; 55 for(j = head[k]; j != -1 ; j = edge[j].next) 56 { 57 Edge e = edge[j]; 58 if(!p[e.to]&&dist[e.to]>dist[k]+e.v) 59 dist[e.to] = dist[k]+e.v; 60 } 61 } 62 } 63 int main() 64 { 65 int n , m , s ; 66 while(~scanf("%d%d%d",&n,&m,&s)) 67 { 68 init(); 69 for(int i = 0 ;i < m ; i++) 70 { 71 int p , q , t ; 72 scanf("%d%d%d",&p,&q,&t); 73 add(q,p,t);//逆向扫描,所以逆向加边 74 } 75 dijk(s,n); 76 int ss; 77 scanf("%d",&ss); 78 int ans = INF; 79 for(int i = 0 ;i < ss; i++) 80 { 81 int w ; 82 scanf("%d",&w); 83 ans = min(ans,dist[w]); 84 } 85 if(ans==INF) printf("-1\n"); 86 else printf("%d\n",ans); 87 } 88 return 0; 89 }
Choose the best route(最短路)dijk
标签:
原文地址:http://www.cnblogs.com/shanyr/p/4681147.html