• HDU 1535 Invitation Cards(SPFA,及其优化)


    题意:

            有编号1~P的站点, 有Q条公交车路线,公交车路线只从一个起点站直接到达终点站,是单向的,每条路线有它自己的车费。

            有P个人早上从1出发,他们要到达每一个公交站点, 然后到了晚上再返回点1。 求所有人来回的最小费用之和。

    思路:

           1.两次SPFA,也就是巧妙的将路线进行了翻转。

    code 1:(数据较大,不能用二维数组,用的邻接表)

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <algorithm>
      4 #include <queue>
      5 using namespace std;
      6 #define MAXN 1000000
      7 #define INF  0x3f3f3f3f
      8 struct node
      9 {
     10     int now,to,w;
     11 }edge[MAXN];//记录每条边的信息,起始点,终止点,权值
     12 int first[MAXN],next[MAXN];
     13 int dis[MAXN],vis[MAXN];
     14 int n,m;
     15 void turnup()//反转图
     16 {
     17     int i,k;
     18     for(i = 0; i<=m; i++)
     19         first[i] = next[i] = -1;
     20     for(i = 0; i<m; i++)
     21     {
     22         k= edge[i].to;
     23         next[i] = first[k];
     24         first[k] = i;
     25     }
     26 }
     27 void SPFA2(int start)
     28 {
     29     int i;
     30     for(i = 0; i<=n; i++)
     31         dis[i] = INF;
     32     dis[start] = 0;
     33     memset(vis,0,sizeof(vis));
     34     queue<int> Q;
     35     Q.push(start);
     36     while(!Q.empty())
     37     {
     38         start = Q.front();
     39         Q.pop();
     40         vis[start] = 0;
     41         i = first[start];
     42         while(1)
     43         {
     44             int to = edge[i].now;
     45             if(dis[to]>dis[start]+edge[i].w)
     46             {
     47                 dis[to]=dis[start]+edge[i].w;
     48                 if(!vis[to])
     49                 {
     50                     vis[to] = 1;
     51                     Q.push(to);
     52                 }
     53             }
     54             i = next[i];
     55             if(i==-1)
     56                 break;
     57         }
     58     }
     59     return;
     60 }
     61 void SPFA1(int start)
     62 {
     63     int i;
     64     for(i = 0; i<=n; i++)
     65         dis[i] = INF;
     66     dis[start] = 0;
     67     memset(vis,0,sizeof(vis));
     68     queue<int> Q;
     69     Q.push(start);
     70     while(!Q.empty())
     71     {
     72         start = Q.front();
     73         Q.pop();
     74         vis[start] = 0;
     75         i=first[start];
     76         while(1)
     77         {
     78             int to = edge[i].to;
     79             if(dis[to]>dis[start]+edge[i].w)
     80             {
     81                 dis[to]=dis[start]+edge[i].w;
     82                 if(!vis[to])
     83                 {
     84                     vis[to] = 1;
     85                     Q.push(to);
     86                 }
     87             }
     88             i = next[i];
     89             if(i==-1)
     90                 break;
     91         }
     92     }
     93     return;
     94 }
     95 int main()
     96 {
     97     int t,sum,i;
     98     scanf("%d",&t);
     99     while(t--)
    100     {
    101         sum = 0;
    102         scanf("%d%d",&n,&m);
    103         for(i=0; i<m; i++)
    104             first[i]=next[i]=-1;
    105         for(i=0; i<m; i++)
    106         {
    107             scanf("%d%d%d",&edge[i].now,&edge[i].to,&edge[i].w);
    108             next[i]=first[edge[i].now];
    109             first[edge[i].now]=i;
    110         }
    111         SPFA1(1);
    112         for(i = 2; i<=n; i++)
    113             sum+=dis[i];
    114         turnup();
    115         SPFA2(1);
    116         for(i = 2; i<=n; i++)
    117             sum+=dis[i];
    118         printf("%d
    ",sum);
    119     }
    120     return 0;
    121 }

    这里SPFA 可以优化,关于SPFA的优化:

    SLF:Small Label First 策略。

      实现方法是,设队首元素为 i,队列中要加入节点 j,在 dj<=di 时加到队首而不是队尾,否则和普通的 SPFA 一样加到队尾。

    LLL:Large Label Last 策略。

      实现方法是,设队列 Q 中的队首元素为 i,距离标号的平均值为 avg(d),每次出队时,若 di>avg(d),把 i 移到队列末尾,如此反复,直到找到一个 i 使 ,di<=avg(d)将其出队。

    ————Anonymous.PJQ
  • 相关阅读:
    测试思想-流程规范 关于预发布环境的一些看法
    Jenkins 开启用户注册机制及用户权限设置
    Jenkins 利用Dashboard View插件管理任务视图
    Loadrunner 脚本开发-从文件读取数据并参数化
    SVN SVN合并(Merge)与拉取分支(Branch/tag)操作简介
    测试思想-流程规范 SVN代码管理与版本控制
    Python 关于Python函数参数传递方式的一点探索
    接口自动化 基于python+Testlink+Jenkins实现的接口自动化测试框架[V2.0改进版]
    Python 解决Python安装包时提示Unable to find vcvarsall.bat的问题
    lintcode :链表插入排序
  • 原文地址:https://www.cnblogs.com/PJQOOO/p/3864905.html
Copyright © 2020-2023  润新知