[SDOI2009]Elaxia的路线

下面的做法虽然能通过此题数据,但其实是错误的。请有兴趣的读者自行研究该算法的错误在哪里。

思路:
标算是跑四趟SPFA,然后拓扑排序求最长链。
我的做法是对于两个起点、终点分别跑一个Dijkstra,然后枚举每个点对,判断是否都在最短路上,并对其距离取$max$。
BZOJ上跑了440ms,内存6556KB,代码长度1906B,比标算不知miao到哪里去了。

 

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<functional>
 4 #include<ext/pb_ds/priority_queue.hpp>
 5 inline int getint() {
 6     char ch;
 7     while(!isdigit(ch=getchar()));
 8     int x=ch^'0';
 9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
10     return x;
11 }
12 const int inf=0x7fffffff;
13 const int V=1501;
14 struct Edge {
15     int to,w;
16 };
17 std::vector<Edge> e[V];
18 inline void add_edge(const int u,const int v,const int w) {
19     e[u].push_back((Edge){v,w});
20 }
21 struct Vertex {
22     int id,dis;
23     bool operator > (const Vertex &another) const {
24         return dis>another.dis;
25     }
26 };
27 int n,s1,t1,s2,t2;
28 int ds1[V],dt1[V],ds2[V],dt2[V];
29 __gnu_pbds::priority_queue<Vertex,std::greater<Vertex> > q;
30 __gnu_pbds::priority_queue<Vertex,std::greater<Vertex> >::point_iterator p[V];
31 inline void Dijkstra(const int s,int *dis) {
32     q.clear();
33     for(int i=1;i<=n;i++) {
34         p[i]=q.push((Vertex){i,dis[i]=(i==s?0:inf)});
35     }
36     while(q.top().dis!=inf) {
37         int x=q.top().id;
38         for(unsigned i=0;i<e[x].size();i++) {
39             Edge &y=e[x][i];
40             if(dis[x]+y.w<dis[y.to]) {
41                 q.modify(p[y.to],(Vertex){y.to,dis[y.to]=dis[x]+y.w});
42             }
43         }
44         q.modify(p[x],(Vertex){x,inf});
45     }
46 }
47 inline bool check(const int x) {
48     return (ds1[x]+dt1[x]==ds1[t1])&&(ds2[x]+dt2[x]==ds2[t2]);
49 }
50 int main() {
51     n=getint();
52     int m=getint();
53     s1=getint(),t1=getint(),s2=getint(),t2=getint();
54     for(int i=0;i<m;i++) {
55         int u=getint(),v=getint(),w=getint();
56         add_edge(u,v,w);
57         add_edge(v,u,w);
58     }
59     Dijkstra(s1,ds1);
60     Dijkstra(t1,dt1);
61     Dijkstra(s2,ds2);
62     Dijkstra(t2,dt2);
63     int ans=0;
64     for(int i=1;i<=n;i++) {
65         if(!check(i)) continue;
66         for(int j=i+1;j<=n;j++) {
67             if(!check(j)) continue;
68             ans=std::max(ans,std::abs(ds1[i]-ds1[j]));
69         }
70     }
71     printf("%d
",ans);
72     return 0;
73 }

 后来把vector改成了数组,跑了436ms,只快了一点点,然而内存翻了三倍。

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<functional>
 4 #include<ext/pb_ds/priority_queue.hpp>
 5 inline int getint() {
 6     char ch;
 7     while(!isdigit(ch=getchar()));
 8     int x=ch^'0';
 9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
10     return x;
11 }
12 const int inf=0x7fffffff;
13 const int V=1501;
14 struct Edge {
15     int to,w;
16 };
17 Edge e[V][V];
18 int sz[V]={0};
19 inline void add_edge(const int u,const int v,const int w) {
20     e[u][sz[u]++]=(Edge){v,w};
21 }
22 struct Vertex {
23     int id,dis;
24     bool operator > (const Vertex &another) const {
25         return dis>another.dis;
26     }
27 };
28 int n,s1,t1,s2,t2;
29 int ds1[V],dt1[V],ds2[V],dt2[V];
30 __gnu_pbds::priority_queue<Vertex,std::greater<Vertex> > q;
31 __gnu_pbds::priority_queue<Vertex,std::greater<Vertex> >::point_iterator p[V];
32 inline void Dijkstra(const int s,int *dis) {
33     q.clear();
34     for(int i=1;i<=n;i++) {
35         p[i]=q.push((Vertex){i,dis[i]=(i==s?0:inf)});
36     }
37     while(q.top().dis!=inf) {
38         int x=q.top().id;
39         for(int i=0;i<sz[x];i++) {
40             Edge &y=e[x][i];
41             if(dis[x]+y.w<dis[y.to]) {
42                 q.modify(p[y.to],(Vertex){y.to,dis[y.to]=dis[x]+y.w});
43             }
44         }
45         q.modify(p[x],(Vertex){x,inf});
46     }
47 }
48 inline bool check(const int x) {
49     return (ds1[x]+dt1[x]==ds1[t1])&&(ds2[x]+dt2[x]==ds2[t2]);
50 }
51 int main() {
52     n=getint();
53     int m=getint();
54     s1=getint(),t1=getint(),s2=getint(),t2=getint();
55     for(int i=0;i<m;i++) {
56         int u=getint(),v=getint(),w=getint();
57         add_edge(u,v,w);
58         add_edge(v,u,w);
59     }
60     Dijkstra(s1,ds1);
61     Dijkstra(t1,dt1);
62     Dijkstra(s2,ds2);
63     Dijkstra(t2,dt2);
64     int ans=0;
65     for(int i=1;i<=n;i++) {
66         if(!check(i)) continue;
67         for(int j=i+1;j<=n;j++) {
68             if(!check(j)) continue;
69             ans=std::max(ans,std::abs(ds1[i]-ds1[j]));
70         }
71     }
72     printf("%d
",ans);
73     return 0;
74 }
View Code

洛谷上跑出来152ms,Rank3。Rank2的做法是Dijkstra+拓扑排序。Rank1怎么跑这么快?

原文地址:https://www.cnblogs.com/skylee03/p/7390094.html