• The Shortest Path in Nya Graph HDU


    题目链接:https://vjudge.net/problem/HDU-4725

    题意:附上一张图吧,把题目的意思画出来,我本来是按照上面的图建图,以为层节点和层上的节点无向就OK了,然后看了别人的代码发现层结点和相邻的层的点都无向,

    然后想到一个样例就是我上面图无法解决的,我把权值和走的边都标出来了,就比较形象,于是去了一行代码加上两行代码就可以过了。

    核心思想就是把每层抽象为一个层节点,层节点到该层的所有点权值为0,就可以了,再加上“层结点和相邻的层的点都无向”,加上点之间的无向边就可以直接跑图了,

    当然,因为点太多O(n^2)已经无法满足了,所有要dijkstra加上堆优化,使得复杂度降到O(nlogn)。

    层节点放在(n + u)个节点上,代码有注释。


      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <queue>
      6 #include <cmath>
      7 #include <iomanip>
      8 using namespace std;
      9 
     10 typedef long long LL;
     11 #define inf (1LL << 29) - 1
     12 #define rep(i,j,k) for(int i = (j); i <= (k); i++)
     13 #define rep__(i,j,k) for(int i = (j); i < (k); i++)
     14 #define per(i,j,k) for(int i = (j); i >= (k); i--)
     15 #define per__(i,j,k) for(int i = (j); i > (k); i--)
     16 
     17 const int N = 100010 * 10;
     18 int n,m,C;
     19 int head[N];
     20 int dis[N];//最短路数组
     21 int app[N]; //存节点存在于第几层
     22 bool vis[N];
     23 int cnt;//链式前向星
     24 struct Edge{
     25 
     26     int to;
     27     int next;
     28     int w;
     29 }edge[N];
     30 
     31 struct Node{
     32     int num;
     33     int W;
     34 
     35     bool friend operator<(Node a,Node b){
     36         return a.W > b.W;
     37     }
     38 };
     39 
     40 void add(int u,int v,int w){
     41 
     42     edge[cnt].to = v;
     43     edge[cnt].w = w;
     44     edge[cnt].next = head[u];
     45     head[u] = cnt++;
     46 }
     47 
     48 //接下来直接是裸的(dijkstra + 优先队列优化)
     49 void dijkstra(){
     50 
     51     rep(i,1,n + n) vis[i] = 0;
     52     rep(i,1,n + n) dis[i] = inf;
     53 
     54     priority_queue<Node> que;
     55     que.push(Node{1,0});
     56     dis[1] = 0;
     57 
     58     while(!que.empty()){
     59 
     60         Node tmp = que.top();   
     61         que.pop();
     62         int u = tmp.num;
     63         if(!vis[u]){
     64             vis[u] = true;
     65 
     66             for(int j = head[u]; ~j; j = edge[j].next){
     67                 
     68                 int v = edge[j].to;
     69                 int w = edge[j].w;
     70                 if(!vis[v] && dis[v] > dis[u] + w){
     71                     dis[v] = dis[u] + w;
     72                     que.push(Node{v,dis[v]});
     73                 }
     74                     
     75             }
     76         }
     77     }
     78 }
     79 
     80 int main(){
     81     
     82     ios::sync_with_stdio(false);
     83     cin.tie(0);
     84 
     85     int T;
     86     cin >> T;
     87 
     88     rep(p,1,T){
     89 
     90         cin >> n >> m >> C;
     91 
     92         rep(i,1,n + n) head[i] = -1;
     93         rep(i,1,n + n) app[i] = -1;
     94         cnt = 1;
     95         rep(i,1,n){ //第几个点
     96             int u;
     97             cin >> u; //属于第几层
     98             add(n + u,i,0); //第u层上加了到第i个点的边,权值为0
     99             // add(i,n + u,0);
    100             app[i] = u;
    101         }
    102 
    103         //相邻层点无向边权值为C
    104         rep__(i,n + 1,n + n){
    105             //相邻层都存在
    106             if(head[i] != -1 && head[i + 1] != -1){
    107                 add(i,i + 1,C);
    108                 add(i + 1,i,C);
    109             }              
    110         }
    111 
    112         //层节点和相邻层的节点进行无向
    113         rep(i,1,n){
    114             if(app[i] == -1) continue;
    115             //下面第二个判断,判断该层是否存在
    116             if(app[i] > 1) if(head[n + app[i] - 1] != -1) add(i,n + app[i] - 1,C);
    117             if(app[i] < n) if(head[n + app[i] + 1] != -1) add(i,n + app[i] + 1,C);
    118         }
    119 
    120         //点之间的无向边
    121         int u,v,w;
    122         rep(i,1,m){
    123         
    124             cin >> u >> v >> w;
    125             add(u,v,w);
    126             add(v,u,w);
    127         }
    128 
    129 
    130         dijkstra();
    131         cout << "Case #" << p << ": ";
    132         if(dis[n] == inf) cout << "-1" << endl;
    133         else cout << dis[n] << endl;
    134     }
    135 
    136 
    137     getchar();getchar();
    138 
    139     return 0;
    140 }
  • 相关阅读:
    2017 Wuhan University Programming Contest (Online Round) Lost in WHU 矩阵快速幂 一个无向图,求从1出发到达n最多经过T条边的方法数,边可以重复经过,到达n之后不可以再离开。
    2017 Wuhan University Programming Contest (Online Round) C. Divide by Six 分析+模拟
    2017 Wuhan University Programming Contest (Online Round) B Color 树形dp求染色方法数
    GCD
    HighCharts SVN IReport进行PDF报表设计--模板
    项目二:品优购 第二天 AngularJS使用 brand商品页面的增删改查
    项目二 品优购第一天
    solr第一天 基础增删改查操作
    solr第二天 京东案例 课程文档 有用
    solr第二天 京东案例
  • 原文地址:https://www.cnblogs.com/SSummerZzz/p/11247226.html
Copyright © 2020-2023  润新知