【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("\n");
84       else printf("NO PATH\n");
85     return 0;
86 }

猜你喜欢

转载自www.cnblogs.com/rabbit1103/p/9446881.html