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 MBSubmit: 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
0 4
0 1 5
1 2 5
2 3 5
3 4 5
2 3 3
0 2 100
Sample Output
8
————————————————