• 【USACO Jan 2011】【洛谷P3008】道路和航线 Roads and Planes


    问题描述

    约翰在外地销售牛奶。这个地方有T个城市,编号为1到T。这些城市间有R条公路和P条 航线。公路都是可以双向通行的,第i条公路连接城市Ai和Bi,过路费为Ci。而航线都是单程 的,第i条航线从城市Xi出发,目的地是城市Yi,机票费为Di,由于航空公司竞争激烈,Di竟 可能是个负数!此外,由于反恐需要,政府在规划交通的时候曾保证,如果Xi到Yi有一条航 线,就不可能从Yi通过其他公路或航线返回Xi。

    约翰拥有世界上公认的最给力的奶牛,所有城市的居民都渴望他的牛奶。约翰已决定将 配送中心设在S城,他想知道将牛奶从S城送到各个城镇的最少费用分别是多少。

    输入格式

    第一行:四个用空格分开的整数:T,R,P,S,1 ≤ S ≤ T ≤ 25000,1 ≤ P, R ≤ 50000 第二行到R + 1行:每行有三个用空格分开的整数,表示一条公路:Ai,Bi和Ci, 1 ≤ Ai,Bi ≤ T,0 ≤ Ci ≤ 10000

    第R + 2行到R + P + 1行:每行有三个用空格分开的整数,表示一条航线:Xi,Yi和Di, 1 ≤ Xi, Yi ≤ T,−10000 ≤ Di ≤ 10000

    输出格式

    第一行到第T行:第K行有一个整数,表示从S到K的最小开销,如果根本到不了K,输出 “NO PATH”

    样例输入

    6 3 3 4

    1 2 5

    3 4 5

    5 6 10

    3 5 -100

    4 6 -100

    1 3 -10

    样例输出

    NO PATH

    NO PATH

    5

    0

    -95

    -100

    提示

    从4 开始,走公路到可以3,从3坐飞机 可以到 5,从 4坐飞机可以到6,但不可能到 1 或2

    题解

    乍一看,最短路,随手打了个spfa就交了,然而这题是卡spfa的。。。

    想到dijkstra堆优化好像是比spfa被卡的时候快的,懒得手打堆,用了STL的优先队列打了dijkstra,顺利过了样例和第二个数据,然而交上去T掉的点比spfa还多Σ(⊙▽⊙”a     (dijkstra优先队列优化的常数比spfa大?)

    于是只好老老实实手打堆。好不容易打好了,样例也过了,第二个数据死活过不了(ಥ﹏ಥ)。

    突然想到dijkstra好像处理不了负权边。。。

    难怪手打堆过不了。。。可是为什么优先队列没有wa?!

    最后还是回到spfa,用了双端队列优化,再加上读入优化和输出优化,于是就过了。

    所谓双端队列优化就是,假设节点v要入队,当前队首元素为u,如果dis[v]<dis[u]就把v插在对头,否则插在队尾。只要在入队的时候稍微改一下就好了。

     1 #include <cstdio>
     2 const int maxn=25000;
     3 struct node{
     4     int u,nex;
     5     int w;
     6 }g[150005];
     7 int n,m,R,P,s,num,fir[25005];
     8 int q[25005],h,t;
     9 int dis[25005];
    10 bool vis[25005];
    11 int read()
    12 {
    13     int f=1,s=0;
    14     char ch;
    15     ch=getchar();
    16     while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    17     if (ch=='-') f=-1,ch=getchar();
    18     while (ch>='0' && ch<='9')
    19       s=s*10+ch-'0',ch=getchar();
    20     return s*f;  
    21 }
    22 void write(int x)
    23 {
    24     if (x<0) putchar('-'),x=-x;
    25     if (x>9) write(x/10);
    26     putchar(x%10+'0');
    27     return;
    28 }
    29 void add(int x,int y,int z)
    30 {
    31     g[++num].u=y;  g[num].w=z;  g[num].nex=fir[x]; fir[x]=num;
    32     return;
    33 }
    34 void spfa()
    35 {
    36     h=0;  t=1;
    37     vis[s]=1;
    38     q[1]=s;
    39     int u,v,d,i,j,k;
    40     while (h!=t)
    41     {
    42         h++;  h%=maxn;  u=q[h];
    43         for (k=fir[u];k;k=g[k].nex)
    44         {
    45             v=g[k].u;
    46             if (dis[u]+g[k].w<dis[v] && v!=s)
    47             {
    48                 dis[v]=dis[u]+g[k].w;
    49                 if (!vis[v])
    50                 {
    51                     vis[v]=1;
    52                     if (dis[v]<dis[q[h+1]])
    53                       q[h]=v,
    54                       h=(h-1+maxn)%maxn;
    55                     else  
    56                       t++,t%=maxn,
    57                       q[t]=v;
    58                 }
    59                   
    60             }
    61         }
    62         vis[u]=0;
    63     }
    64     return;
    65 }
    66 int main()
    67 {
    68     int i,j,k,x,y,z;
    69     //scanf("%d%d%d%d",&n,&R,&P,&s);
    70     n=read();  R=read();  P=read();  s=read();
    71     for (i=1;i<=R;i++)
    72       //scanf("%d%d%d",&x,&y,&z),
    73       x=read(),y=read(),z=read(),
    74       add(x,y,z),add(y,x,z);
    75     for (i=1;i<=P;i++)
    76       //scanf("%d%d%d",&x,&y,&z),
    77       x=read(),y=read(),z=read(),
    78       add(x,y,z);
    79     for (i=1;i<=n;i++) dis[i]=1e9;
    80     dis[s]=0;  
    81     spfa();
    82     for (i=1;i<=n;i++)
    83       if (dis[i]<1e9) write(dis[i]),printf("
    ");
    84       else printf("NO PATH
    ");
    85     return 0;
    86 }
  • 相关阅读:
    debian7.2+nginx+mysql
    VirtualBox为虚拟OS硬盘扩容
    VirtualBox-Debian7.2-share
    linux 标准化
    linux user date
    Array方法总结
    GET和POST区别 / doGet()和doPost()的区别
    servlet错误:HTTP Status 405
    python类型转换、数值操作
    Architecture:话说科学家/工程师/设计师/商人
  • 原文地址:https://www.cnblogs.com/rabbit1103/p/9446881.html
Copyright © 2020-2023  润新知