• SDUT2493 Constructing Roads(最短路,spfa)


    题目链接

    分析:

    本题就是有一条边的权值可以减半情况下的求两点间的最短路。

    一开始我想的是先求出不考虑减半情况下的最短路,然后将最短路中的最大权值减半。这样得到的结果是不对的。如下图:

    如果先找不减半最短路1->2->3。总花费为11。将最大的8除以2,所得结果为7。而从1到3将边权减半得到的是6.所以符合题意的最短路应该为1->3。所以先不考虑减半求最短路的想法是走不通的。

    如此的话,本题可以用两次spfa分别求两个点到所有点的最短路,然后分别枚举每一条边权值减半的情况。

    AC(未优化)代码如下:

    View Code
    #include <cstdio>
    #include <cstring>
    #include <queue>
    
    using namespace std;
    
    const int INF = (1<<28);
    
    #define MAXN 1010
    #define MAXM 50010
    
    struct node{
        int u, v, w;
        int next;
    }edge[MAXM*2];
    
    queue<int> q;
    int head[MAXN], n, m, top, vis[MAXN], d1[MAXN], d2[MAXN];
    
    void Init(){
        int i;
        top = 0;
        for(i=1; i<=n; i++){
            head[i] = -1;
        }
    }
    
    void add(int u, int v, int w){
        edge[top].u = u;
        edge[top].v = v;
        edge[top].w = w;
        edge[top].next = head[u];
        head[u] = top++;
    }
    
    void spfa(int v0, int *d){
        int u, i;
    
        for(i=1; i<=n; i++) {d[i] = INF; vis[i] = 0;}
    
        d[v0] = 0;
        vis[v0] = 1;
        q.push(v0);
    
        while(!q.empty()){
            u = q.front(); q.pop();
            vis[u] = 0;
            for(i=head[u]; i != -1; i = edge[i].next){
                int v = edge[i].v, w = edge[i].w;
                if(d[u]+w < d[v]){
                    d[v] = d[u]+w;
                    if(!vis[v]){
                        vis[v] = 1;
                        q.push(v);
                    }
                }
            }
        }
    }
    
    int _min(int x, int y){
        return x < y ? x : y;
    }
    
    int main(){
        int i, u, v, w, s, e, min_num;
    
        while(scanf("%d %d", &n, &m) == 2){
            Init();
            min_num = INF;
            for(i=0; i<m; i++){
                scanf("%d %d %d", &u, &v, &w);
                add(u, v, w);
                add(v, u, w);
            }
            scanf("%d %d", &s, &e);
            spfa(s, d1); spfa(e, d2);
    
            if(d1[e] >= INF || d2[s] >= INF) {printf("No solution\n"); continue;}
    
            for(i=0; i<top; i++){
                min_num = _min(min_num, d1[edge[i].u]+edge[i].w/2+d2[edge[i].v]);
            }
    
            printf("%d\n", min_num);
        }
    
        return 0;
    }

     学了一下slf优化,但对本题而言,优化后和未优化跑时是差不多的。

    AC(slf优化)代码如下:

    View Code
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <deque>
     4 
     5 using namespace std;
     6 
     7 const int INF = (1<<28);
     8 
     9 #define MAXN 1010
    10 #define MAXM 50010
    11 
    12 struct node{
    13     int u, v, w;
    14     int next;
    15 }edge[MAXM*2];
    16 
    17 deque<int> q;
    18 int head[MAXN], n, m, top, vis[MAXN], d1[MAXN], d2[MAXN];
    19 
    20 void Init(){
    21     int i;
    22     top = 0;
    23     for(i=1; i<=n; i++){
    24         head[i] = -1;
    25     }
    26 }
    27 
    28 void add(int u, int v, int w){
    29     edge[top].u = u;
    30     edge[top].v = v;
    31     edge[top].w = w;
    32     edge[top].next = head[u];
    33     head[u] = top++;
    34 }
    35 
    36 void spfa(int v0, int *d){
    37     int u, i;
    38 
    39     for(i=1; i<=n; i++) {d[i] = INF; vis[i] = 0;}
    40 
    41     d[v0] = 0;
    42     vis[v0] = 1;
    43     q.push_back(v0);
    44 
    45     while(!q.empty()){
    46         u = q.front(); q.pop_front();
    47         vis[u] = 0;
    48         for(i=head[u]; i != -1; i = edge[i].next){
    49             int v = edge[i].v, w = edge[i].w;
    50             if(d[u]+w < d[v]){
    51                 d[v] = d[u]+w;
    52                 if(!vis[v]){
    53                     vis[v] = 1;
    54                     if(!q.empty()){
    55                         if(d[v]>d[q.front()]) q.push_back(v);
    56                         else q.push_front(v);
    57                     }
    58                     else q.push_back(v);
    59                 }
    60             }
    61         }
    62     }
    63 }
    64 
    65 int _min(int x, int y){
    66     return x < y ? x : y;
    67 }
    68 
    69 int main(){
    70     int i, u, v, w, s, e, min_num;
    71 
    72     while(scanf("%d %d", &n, &m) == 2){
    73         Init();
    74         min_num = INF;
    75         for(i=0; i<m; i++){
    76             scanf("%d %d %d", &u, &v, &w);
    77             add(u, v, w);
    78             add(v, u, w);
    79         }
    80         scanf("%d %d", &s, &e);
    81         spfa(s, d1); spfa(e, d2);
    82 
    83         if(d1[e] >= INF || d2[s] >= INF) {printf("No solution\n"); continue;}
    84 
    85         for(i=0; i<top; i++){
    86             min_num = _min(min_num, d1[edge[i].u]+edge[i].w/2+d2[edge[i].v]);
    87         }
    88 
    89         printf("%d\n", min_num);
    90     }
    91 
    92     return 0;
    93 }
  • 相关阅读:
    实验楼第二期比赛第二题
    基础练习题
    基本数据类型:数字、字符串、列表、元祖、字典、集合
    二进制与十进制转换
    Python基础--1.2 变量循环基础介绍
    Python基础--1.1Python基础介绍
    旋转木马特效代码
    javascript中全屏滑动效果实现
    正则基础知识总结
    getElementsByClassName 方法兼容性封装方法二
  • 原文地址:https://www.cnblogs.com/tanhehe/p/2940449.html
Copyright © 2020-2023  润新知