洛谷P3008 [USACO11JAN]Roads and Planes G

 

 

 洛谷P3008 [USACO11JAN]Roads and Planes G

 

 

 洛谷P3008 [USACO11JAN]Roads and Planes G

 

思路分析:

解法一:

  由于这道题提到可能有负权边,那么dijsktra算法肯定首先就被我们排除了,floyd?想都不要想,最后我们只剩下了Spfa,但众所周知,USACO是卡Spfa的,但似乎没有其他的解法了,于是我们就可以像一道最短路板子题一样建图,从起点出发,跑一遍Spfa,交上去,果不其然,TLE掉了两个点。但也只有两个点,于是我们想到用SLF去优化它,所谓SLF,就是在Spfa入队时拿将要入队的数和队首元素比较,如果比队首元素小则插入队首,否则插在対尾,于是用到双端队列,每次入队前判断一下就好了。这样我们就可以在开O2的前提下水过这道题了,但不开O2还是会TLE掉一个点,其实这道题只是不想卡SLF,但SLF优化并没有基于复杂度,实际上可以构造数据来卡到2^n,甚至可能比普通spfa更慢(以上一句话来自洛谷大佬(id:1010_)),但既然能过,也是一种方法。

上代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<queue>
 5 using namespace std;
 6 #define debug printf("------------\n");
 7 const int N=1e6+10;
 8 int Head[N],tot,T,P,R,S,dis[N],vis[N];
 9 struct Node{
10     int next,to,dis;
11 }edge[N];
12 void Add(int x,int y,int z){
13     edge[++tot].to=y;
14     edge[tot].next=Head[x];
15     edge[tot].dis=z;
16     Head[x]=tot;
17 }
18 void Spfa(int x){
19     memset(dis,0x3f,sizeof(dis));
20     memset(vis,0,sizeof(vis));
21     deque<int>q;    //只有这里不同,其他都是板子 
22     q.push_back(x);vis[x]=1;dis[x]=0;
23     while(!q.empty()){
24         int u=q.front();q.pop_front();
25         for(int i=Head[u];i;i=edge[i].next){
26             int v=edge[i].to;vis[u]=0;
27             if(dis[v]>dis[u]+edge[i].dis){
28                 dis[v]=dis[u]+edge[i].dis;
29                 if(!vis[v]){
30                     if(!q.empty()&&dis[v]>=dis[q.front()])
31                         q.push_back(v);
32                     else q.push_front(v);
33                     vis[v]=1;
34                 }
35             }
36         }
37     }
38 }
39 int main(){
40 //    freopen("a.txt","r",stdin);
41 //    freopen("my.txt","w",stdout);
42     scanf("%d%d%d%d",&T,&R,&P,&S);
43     for(int i=1;i<=R;++i){
44         int x,y,z;
45         scanf("%d%d%d",&x,&y,&z);
46         Add(x,y,z);Add(y,x,z);
47     }
48     for(int i=1;i<=P;++i){
49         int x,y,z;
50         scanf("%d%d%d",&x,&y,&z);
51         Add(x,y,z);
52     }
53     Spfa(S);
54     for(int i=1;i<=T;++i){
55         if(dis[i]==0x3f3f3f3f)
56             printf("NO PATH\n");
57         else printf("%d\n",dis[i]);
58     }
59     return 0;
60 }
View Code

相关文章:

  • 2022-02-13
  • 2022-12-23
  • 2021-09-29
  • 2021-08-08
  • 2021-11-09
  • 2021-09-07
  • 2021-10-09
  • 2022-01-05
猜你喜欢
  • 2021-05-25
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-12-05
  • 2021-11-09
  • 2021-05-19
相关资源
相似解决方案