zoukankan      html  css  js  c++  java
  • 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 eq 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。

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

  • 相关阅读:
    ListBox的数据绑定
    GridView中加入新行方法
    一个事务的例子
    用sql语句查询从N条到M条的记录
    用户注册表中日期输入的解决方案
    对分页控件进行分页的封装
    我的触发器
    缓存DataSet以提高性能
    网站访问统计在Global.asax中的配置
    给表格控件绑定数据库内容的封装
  • 原文地址:https://www.cnblogs.com/ZERO-/p/10362809.html
Copyright © 2011-2022 走看看