zoukankan      html  css  js  c++  java
  • CF938D Buy a Ticket

     

    思路分析:从数据范围我们可以看出,从每个点跑一遍最短路肯定是不行的,于是我们想,这道题的行走方式可以简单优化一下,我们在建图时建上双倍边权,就不用再考虑来回了,之后再来考虑点权的问题,我们在从一个点出发,经过几个点,最终到达目的地,只用到了一次点权,即终点的点权。于是我们是不是可以倒着走呢?从终点向起点前进,路程都是一样的。很久之前我们曾做过一道“挖水井”的题目。那道题用到了虚点的思路,当然我们这道题也能用,我们建一个虚点,它和其他节点的边权就是当地门票钱。之后从虚点出发跑一下最短路,我们就可以解决这道问题了。(Spfa会超时!!!会超时!!!会超时!!!)。

    代码:

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<queue>
     5 using namespace std;
     6 const int N=1e6+10;
     7 typedef long long ll;
     8 struct Node{
     9     int next,to;
    10     ll dis;
    11 }edge[N];
    12 int Head[N],tot;
    13 int n,m;
    14 void Add(int x,int y,ll z){
    15     edge[++tot].to=y;
    16     edge[tot].next=Head[x];
    17     edge[tot].dis=z;
    18     Head[x]=tot;
    19 }
    20 struct Edge{
    21     ll dis;
    22     int num;
    23     Edge(int x,ll y){
    24         num=x;dis=y;
    25     }
    26     bool operator < (const Edge& a)const{
    27         return a.dis<dis;
    28     }
    29 };
    30 ll dis[N];
    31 int vis[N];
    32 priority_queue<Edge>q;
    33 void dijkstra(int x){
    34     for(int i=1;i<=n+1;++i)
    35         dis[i]=2e13;
    36     memset(vis,0,sizeof(vis));
    37     q.push(Edge(x,0));
    38     dis[x]=0;
    39     while(!q.empty()){
    40         Edge top=q.top();q.pop();
    41         if(vis[top.num]) continue;
    42         vis[top.num]=1;
    43         int u=top.num;
    44         for(int i=Head[u];i;i=edge[i].next){
    45             int v=edge[i].to;
    46             if(dis[v]>dis[u]+edge[i].dis){
    47                 dis[v]=dis[u]+edge[i].dis;
    48                 q.push(Edge(v,dis[v]));
    49             }
    50         }
    51     }
    52 }
    53 ll cost[N];
    54 int main(){
    55     scanf("%d%d",&n,&m);
    56     for(int i=1;i<=m;++i){
    57         int x,y;
    58         ll z;
    59         scanf("%d%d%lld",&x,&y,&z);
    60         Add(x,y,2*z);Add(y,x,2*z);
    61     }
    62     for(int i=1;i<=n;++i){
    63         scanf("%lld",&cost[i]);
    64         Add(n+1,i,cost[i]);
    65     }
    66     dijkstra(n+1);
    67     for(int i=1;i<=n;++i)
    68         printf("%lld ",dis[i]);
    69     puts("");
    70     return 0;
    71 }
    View Code
  • 相关阅读:
    VSCode配置Python开发环境
    图像特征——边缘
    关于相机内参中的焦距fx和fy
    摄影变换和仿射变换
    为什么要引入齐次坐标
    链表一
    从小问题看懂链表
    类与对象
    排序一
    数组
  • 原文地址:https://www.cnblogs.com/li-jia-hao/p/12977454.html
Copyright © 2011-2022 走看看