Comet OJ CCPC-Wannafly Winter Camp Day1 (Div2, online mirror) F.爬爬爬山-最短路(Dijkstra)(两个板子)+思维(mdzz...) zhixincode

 

9.83%

Total Submission:417

Total Accepted:41

题目描述

 

爬山是wlswls最喜欢的活动之一。

在一个神奇的世界里,一共有nn座山,mm条路。

wlswls初始有kk点体力,在爬山的过程中,他所处的海拔每上升1m1m,体力会减11点,海拔每下降1m1m,体力会加一点。

现在wlswls想从11号山走到nn号山,在这个过程中,他的体力不能低于00,所以他可以事先花费一些费用请dlsdls把某些山降低,将一座山降低ll米需要花费l*lll的代价,且每座山的高度只能降低一次。因为wlswls现在就在11号山上,所以这座山的高度不可降低。

wlswls从11号山到nn号山的总代价为降低山的高度的总代价加上他走过的路的总长度。

wlswls想知道最小的代价是多少。

 

 
 

输入描述

 

第一行三个整数nn,mm,kk。

接下来一行nn个整数,第ii个整数h_ihi表示第ii座山的高度。

接下来mm行,每行三个整数xx,yy,zz表示xyxy之间有一条长度为zz的双向道路。

经过每条路时海拔是一个逐步上升或下降的过程。

数据保证11号山和nn号山联通。

1 \leq n, k, h_i, z \leq 1000001n,k,hi,z100000

1 \leq m \leq 2000001m200000

1 \leq x, y \leq n1x,yn

x \neq yx̸=y

 

输出描述

 

一行一个整数表示答案。

 

样例输入 1 

4 5 1
1 2 3 4
1 2 1
1 3 1
1 4 100
2 4 1
3 4 1

样例输出 1

6

 

 

去年的题,其实当时写了,两个板子,有一个过了一个没过,今天又看到这道题了,打算改一改,改了一下午,一直过不去,最后发现初始化有点问题,有一个是比数据范围大一点点的初始化,一个是直接memset初始化,因为以前memset初始化写超时过,所以就没在意,结果发现就是这里错了。。。啊啊啊啊啊啊啊啊啊,哭死。初始化的时候,要比最大值大一点初始化,for循环的初始化,改成1e18就可以。之所以memset是对的,是因为填充的时候,inf比实际的要大。

思路就是把体力值加到路径里面,然后想一想,发现有几分道理,只要往上走才会掉值,emnnnn,反正感觉有点怪,就是把体力值加到路径里面然后跑个最短路就可以了。

 

两个版本的dijkstra,随便看着玩吧。。。

 

代码1(短一点):

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<bitset>
 6 #include<cassert>
 7 #include<cctype>
 8 #include<cmath>
 9 #include<cstdlib>
10 #include<ctime>
11 #include<deque>
12 #include<iomanip>
13 #include<list>
14 #include<map>
15 #include<queue>
16 #include<set>
17 #include<stack>
18 #include<vector>
19 using namespace std;
20 typedef long long ll;
21 typedef long double ld;
22 typedef pair<int,int> pii;
23 
24 const double PI=acos(-1.0);
25 const double eps=1e-6;
26 const ll mod=1e9+7;
27 const int inf=0x3f3f3f3f;
28 const int maxn=1e5+10;
29 const int maxm=100+10;
30 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
31 
32 int n,m,k;
33 int cnt=0,head[maxn<<2];
34 bool vist[maxn];
35 ll dis[maxn],body[maxn];
36 priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > >q;
37 
38 struct node{
39     int v,nex;
40     ll w;
41 }edge[maxn<<2];
42 
43 void add(int u,int v,ll w)
44 {
45     edge[cnt].v=v;
46     edge[cnt].w=w;
47     edge[cnt].nex=head[u];
48     head[u]=cnt++;
49 }
50 
51 void dijkstra(int s)
52 {
53     dis[s]=0;//到自己的最短距离直接设为0
54     q.push(make_pair(0,s));
55     while(!q.empty()){//队列非空
56         int u=q.top().second;q.pop();
57         vist[u]=true;
58         for(int i=head[u];~i;i=edge[i].nex){
59             int v=edge[i].v;
60             ll w=edge[i].w+(body[v]>k?(body[v]-k)*(body[v]-k):0);
61             if(dis[v]>dis[u]+w){//满足条件更新距离
62                 dis[v]=dis[u]+w;
63                 //p[v]=u;//保存路径
64                 q.push(make_pair(dis[v],v));//把更新完的值压入队列
65             }
66         }
67     }
68 }
69 
70 int main()
71 {
72     memset(head,-1,sizeof(head));//初始化数组
73     memset(vist,false,sizeof(vist));
74     memset(dis,inf,sizeof(dis));
75     cin>>n>>m>>k;
76     for(int i=1;i<=n;i++)
77         cin>>body[i];
78     for(int i=1;i<=m;i++){
79         int u,v;ll w;
80         cin>>u>>v>>w;
81         add(u,v,w);
82         add(v,u,w);//无向图相互可达 有向图一次就好
83     }
84     k+=body[1];
85     dijkstra(1);
86     cout<<dis[n]<<endl;
87 }

 

代码2(队友的板子,哈哈哈哈):

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<bitset>
  6 #include<cassert>
  7 #include<cctype>
  8 #include<cmath>
  9 #include<cstdlib>
 10 #include<ctime>
 11 #include<deque>
 12 #include<iomanip>
 13 #include<list>
 14 #include<map>
 15 #include<queue>
 16 #include<set>
 17 #include<stack>
 18 #include<vector>
 19 using namespace std;
 20 typedef long long ll;
 21 typedef long double ld;
 22 typedef pair<int,int> pii;
 23 
 24 const double PI=acos(-1.0);
 25 const double eps=1e-6;
 26 const ll mod=1e9+7;
 27 const int inf=0x3f3f3f3f;
 28 const int maxn=1e5+10;
 29 const int maxm=100+10;
 30 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
 31 
 32 int n,m,k;
 33 int done[maxn],p[maxn];//d[i]表示i点到起点s的最短路距离,p[i]表示起点s到i的最短路径与i点相连的上一条边
 34 ll d[maxn],body[maxn];//done[u]==1表示u点到起点s的最短路已经找到
 35 
 36 struct edge{         //边结构体;
 37     int from,to;
 38     ll dis;
 39 };
 40 
 41 vector<edge> edges;     //边集 无向图 边数*2
 42 vector<int> g[maxn];    //g数组存的是边的序号
 43 
 44 struct mindis{           //压入优先队列的结构体 因为d[u]和u要绑定起来 才可标记 u是否已确定最短路;
 45     ll d;
 46     int u;
 47 
 48     bool operator <(const mindis& rhs)const{
 49         return d>rhs.d;         //距离最小值优先 距离相等无所谓 随便一个先出 边权是正的 两个会依次访问 不会影想结果
 50     }
 51 };
 52 
 53 priority_queue<mindis> q;   //优先队列 小顶堆 最小值优先
 54 
 55 void addedge(int from,int to,ll dis)      //加边操作
 56 {
 57     edges.push_back((edge){from,to,dis});   //将边压入边集
 58     int k=edges.size();
 59     g[from].push_back(k-1);                 //k-1为边序号 以后调用边集数组要从下标0开始 所以边的编号从0开始 将边序号压入已from为起点的数组
 60 }
 61 
 62 void dijkstra(int s)     //主算法
 63 {
 64     d[s]=0;                     //到自己的最短距离直接设为0
 65     q.push((mindis){0,s});
 66     while(!q.empty()){              //队列非空
 67         mindis x=q.top();           //取当前最小值
 68         q.pop();
 69         int u=x.u;
 70         if(done[u]==1) continue;    //已确定路径直接跳过
 71         done[u]=1;                  //标记 已确定
 72         for(int i=0;i<g[u].size();i++){
 73             edge e=edges[g[u][i]];  //g[u][i]表示以u为起点的第i条边在边集edges中的下标
 74             ll w=e.dis+(body[e.to]>k?(body[e.to]-k)*(body[e.to]-k):0);
 75             if(d[e.to]>d[u]+w){     //满足条件更新距离
 76                 d[e.to]=d[u]+w;
 77                 p[e.to]=g[u][i];       //保存路径
 78                 q.push((mindis){d[e.to],e.to});  //把更新完的值压入队列
 79             }
 80         }
 81     }
 82 }
 83 
 84 int main()
 85 {
 86     memset(done,0,sizeof(done));  //初始化数组
 87     memset(p,-1,sizeof(p));
 88     //memset(d,inf,sizeof(d));
 89     cin>>n>>m>>k;
 90     for(int i=0;i<=n;i++)      //把距离初始化为 inf  不能用memset  自己估算一下路径最长有多长 inf定义大一点就好
 91         d[i]=1e18;
 92     for(int i=1;i<=n;i++)
 93         cin>>body[i];
 94     for(int i=1;i<=m;i++){
 95         int u,v;ll w;
 96         cin>>u>>v>>w;
 97         addedge(u,v,w);
 98         addedge(v,u,w);             //无向图相互可达 有向图一次就好
 99     }
100     k+=body[1];
101     dijkstra(1);
102     cout<<d[n]<<endl;
103 }

 

 

好想找队友聊天,但是放假了,不能打扰,超乖.jpg。

 

 

溜了,我姐的狗窝没有吃的,要饿死了(;´д`)ゞ

 

posted @ 2019-02-11 18:26  ZERO-  阅读(525)  评论(0编辑  收藏  举报