BZOJ2763, 最短路

好激动,没想到,我在这个网站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(), k = 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(), k = 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 }
时间: 2024-11-04 16:59:21

BZOJ2763, 最短路的相关文章

bzoj2763 最短路

在我看来相当于拆点 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #include<vector> 7 #include<queue> 8 #define rep(i,l,r) for(int i=l;i<r;i++) 9 #define clr(a,x) me

BZOJ2763[JLOI2011]飞行路线 [分层图最短路]

2763: [JLOI2011]飞行路线 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2523  Solved: 946[Submit][Status][Discuss] Description Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司.该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定的价格.Alice和Bob现在要从一个城市沿着航线到达另一个城市

bzoj2763:最短路

最短路,然后可以有多次免费的机会,不难写,但是最短路这次试着用指针写果然快了点,一开始看错数据范围数组开太大tle: ---------------------------------------------------------------------------------------------- #include<cstdio>#include<cstring>#include<queue>#include<iostream>#include<

BZOJ2763 JLOI2011 飞行路线 最短路

题意:给定一张图,有可以将K条路径的花费变为0,求从1到N的最短路 题解: 分层图+最短路水过. 我们把原图复制K份,平行的放在一起(就像饼干一样一层层的),然后给每个图编号1 2 3……K,然后对于原图中每一条边(x,y),在i的x和i+1的y之间连一条边权为0的边,然后在这K个图上做最短路即可. 当然这只是个思想,实际上你只需要多开一维记录在哪个层里即可,不用真的再去开N*(K-1)个点. #include <queue> #include <cstdio> #include

HDU5669 Road 分层最短路+线段树建图

分析:(官方题解) 首先考虑暴力,显然可以直接每次O(n^2) ?的连边,最后跑一次分层图最短路就行了. 然后我们考虑优化一下这个连边的过程 ,因为都是区间上的操作,所以能够很明显的想到利用线段树来维护整个图, 连边时候找到对应区间,把线段树的节点之间连边.这样可以大大缩减边的规模,然后再跑分层图最短路就可以了. 但是这样建图,每一次加边都要在O(logn)个线段树节点上加边,虽然跑的非常快,但是复杂度仍然是不科学的. 为了解决边的规模的问题,开两棵线段树,连边时候可以新建一个中间节点,在对应区

bzoj2763 飞行路线 二维SPFA

填坑填坑填坑--链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2763 题意:有$m$次免费机会,求出最小值. 二维最短路没什么说的.注意时间很坑人,要用双端队列优化$SPFA$(我再说一遍堆优化SPFA是不存在的--) 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using na

hdu3461Marriage Match IV 最短路+最大流

//给一个图.给定起点和终点,仅仅能走图上的最短路 //问最多有多少种走的方法.每条路仅仅能走一次 //仅仅要将在最短路上的全部边的权值改为1.求一个最大流即可 #include<cstdio> #include<cstring> #include<iostream> #include<queue> #include<vector> using namespace std ; const int inf = 0x3f3f3f3f ; const

UESTC30-最短路-Floyd最短路、spfa+链式前向星建图

最短路 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的T-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗? Input 输入包括多组数据. 每组数据第一行是两个整数NN ,MM (N≤100N≤100 ,M≤10000M≤1000

ACM: HDU 2544 最短路-Dijkstra算法

HDU 2544最短路 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Description 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗? Input 输入包括多组数据.每组数据第一行是两个整数N.M(N<=100,M<