zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    linux___用户管理
    linux基础_vim命令
    linux
    linux_centos安装
    python基础1_哈希碰撞的认识
    oop对象,面向对象
    Oracle数据库—— 事务处理与并发控制
    Oracle数据库——索引、视图、序列和同义词的创建
    Oracle数据库——触发器的创建与应用
    Oracle数据库—— 存储过程与函数的创建
  • 原文地址:https://www.cnblogs.com/PJQOOO/p/3864905.html
Copyright © 2011-2022 走看看