BZOJ2763, 最短路

   

   好激动,没想到,我在BZOJ这个网站AC的第一道是一个最短路的,虽然仔细一想也不是很难。

   简单说一下吧!之所以开始做这道题还是想练一下最短路,因为刚重温了一下dijkstra。刚开始看到也是又蒙了,然后仔细一想,状态的转移应该不难,应该是分层进行的,不断地进行下一步决策。所以就把刘汝佳的dijkstra算法改了一下,用在这道题;

   

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<queue>
  4 #include<vector>
  5 #include<cstring>
  6 #define rep(i,j,k) for(int i = j; i <= k; i++)
  7 #define maxn 10005
  8 #define INF 0xfffffff;
  9 using namespace std;
 10  
 11 int n, s, t, k, m;
 12  
 13 int read()
 14 {
 15     int s = 0, t = 1; char  c = getchar();
 16     while( !isdigit(c) ){
 17         if( c == '-' ) t = -1; c = getchar();
 18     }
 19     while( isdigit(c) ){
 20         s = s * 10 + c - '0'; c = getchar();
 21     }
 22     return s * t;
 23 }
 24  
 25 struct heapnode{
 26 int d, u, zhi;
 27 bool operator < (const heapnode& rhs) const{
 28   return d > rhs.d; 
 29 }
 30 };
 31  
 32 struct edge{
 33 int from, to, key;
 34 };
 35  
 36 struct Dijkstra{
 37 int n, k;
 38 vector<edge> edges;
 39 vector<int> q[maxn];
 40 int d[maxn][15];
 41 bool done[maxn][15];
 42  
 43 void init(int n,int k)
 44 {
 45     this->n = n;
 46     this->k = k;
 47     rep(i,0,n-1){
 48         q[i].clear();
 49     }
 50     edges.clear();
 51 }
 52  
 53 void dijkstra(int s)
 54 {
 55     rep(i,0,n-1) rep(j,0,k) d[i][j] = INF;
 56     rep(i,0,k) d[s][i] = 0;
 57     priority_queue<heapnode> Q;
 58     Q.push((heapnode){0,s,0});
 59     memset(done,0,sizeof(done));
 60     while( !Q.empty() ){
 61         heapnode x = Q.top(); Q.pop();
 62         int u = x.u;
 63         int zhi = x.zhi;
 64         if( done[u][zhi] ) continue;
 65         done[u][zhi] = 1;
 66         int s = q[u].size();
 67         rep(i,0,s-1){
 68             edge& x = edges[q[u][i]];
 69             int y = x.to;
 70             if( d[y][zhi] > d[u][zhi] + x.key ){
 71                 d[y][zhi] = d[u][zhi] + x.key;
 72                 Q.push((heapnode){d[y][zhi],y,zhi}); 
 73             } 
 74             if( d[y][zhi+1] > d[u][zhi] && zhi < k ){
 75                 d[y][zhi+1] = d[u][zhi]; 76                 Q.push((heapnode){d[y][zhi+1],y,zhi+1});
 77             }
 78         }
 79     } 
 80 }
 81  
 82 void add_edge(int x,int y,int key)
 83 {
 84     edges.push_back((edge){x,y,key});
 85     edges.push_back((edge){y,x,key});
 86     int m = edges.size();
 87     q[x].push_back(m-2);
 88     q[y].push_back(m-1);
 89 }
 90 };
 91  
 92 Dijkstra solver;
 93  
 94 int main()
 95 {
 96     n = read(), m = read(), xk = read(), s = read(), t = read();
 97     solver.init(n,k);
 98     rep(i,1,m){
 99         int x = read(), y = read(), key = read();
100         solver.add_edge(x,y,key);
101     } 
102     solver.dijkstra(s);
103     int ans = 0xfffffff;
104     rep(i,0,k){
105         ans = min(solver.d[t][i],ans);
106     }
107     cout<<ans<<endl;
108     return 0;
109 }

     同学说,指针版能更快一些,就学着打了个指针版,加油,也不难。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<queue>
 5 #define rep(i,j,k) for(int i = j; i <= k; i++)
 6 #define maxn 10005
 7 #define maxl 50003
 8 #define clr(i,l) memset(i,l,sizeof(i));
 9 using namespace std;
10 
11 int n, m, s, t, xk;
12 int d[maxn][13] = {0}; 
13 
14 int read()
15 {
16     int s = 0, t = 1; char c = getchar();
17     while( !isdigit(c) ){
18         if( c == '-' ) t = -1; c = getchar();
19     }
20     while( isdigit(c) ){
21         s = s * 10 + c - '0'; c = getchar();
22     }
23     return s * t;
24 }
25 
26 struct edge{
27 int to, key;
28 edge* next;
29 };
30 
31 struct heapnode{
32 int r, k, u;
33 bool operator < (const heapnode& rhs) const{
34   return r > rhs.r;
35 }
36 };
37 
38 priority_queue<heapnode> Q;
39 
40 edge edges[maxl*2];
41 edge* pt;
42 edge* head[maxn];
43 
44 void add_edge(int x,int y,int key)
45 {
46     pt->to = y;
47     pt->key = key;
48     pt->next = head[x];
49     head[x] = pt++;
50     pt->to = x;
51     pt->key = key;
52     pt->next = head[y];
53     head[y] = pt++;
54 }
55 
56 void dijkstra()
57 {
58     clr(d,127); clr(d[s],0);
59     Q.push((heapnode){0,0,s});
60     while( !Q.empty() ){
61         heapnode x = Q.top(); Q.pop();
62         int u = x.u, k= x.k;
63         if( x.r != d[u][k] ) continue;
64         for( edge*i = head[u]; i ; i = i->next ){
65             int t = i->to;
66             if( d[t][k] > d[u][k] + i->key ) {
67                 d[t][k] = d[u][k] + i->key;
68                 Q.push((heapnode){d[t][k],k,t});
69             }
70             if( d[t][k+1] > d[u][k] && k < xk ){
71                 d[t][k+1] = d[u][k];
72                 Q.push((heapnode){d[t][k+1],k+1,t});
73             }
74         }
75     }
76 }
77 
78 int main()
79 {
80     n = read(), m = read(), xk = read(), s = read(), t = read();
81     pt = edges;
82     rep(i,1,m){
83         int x = read(), y = read(), key = read();
84         add_edge(x,y,key);
85     }
86     dijkstra();
87     int ans = 0xfffffff;
88     rep(i,0,xk){
89         ans = min(ans,d[t][i]);
90     }
91     cout<<ans<<endl;
92     return 0;
93 }

 

2763: [JLOI2011]飞行路线

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1462  Solved: 564
[Submit][Status][Discuss]

Description

Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定的价格。Alice和Bob现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多k种航线上搭乘飞机。那么Alice和Bob这次出行最少花费多少?

Input

数据的第一行有三个整数,n,m,k,分别表示城市数,航线数和免费乘坐次数。
第二行有两个整数,s,t,分别表示他们出行的起点城市编号和终点城市编号。(0<=s,t<n)
接下来有m行,每行三个整数,a,b,c,表示存在一种航线,能从城市a到达城市b,或从城市b到达城市a,价格为c。(0<=a,b<n,a与b不相等,0<=c<=1000)
 

Output

 
只有一行,包含一个整数,为最少花费。

Sample Input

5 6 1
0 4
0 1 5
1 2 5
2 3 5
3 4 5
2 3 3
0 2 100

Sample Output

8

posted on 2015-12-10 19:43  83131  阅读(158)  评论(0编辑  收藏  举报

导航