AcWing342道路与航线
思路:
看起来非常裸的spfa,然而精心构造的数据卡了。
就用到spfa的SLF优化,我们之前的spfa都是用队列实现的,每个数据都放到队尾。现在我们用双端队列,如果当前点的权值少于我们当前队头点的权值的话,那么我们就将这个节点插入到队头,否则我们插入到队尾。
代码:
#include<bits/stdc++.h>
#define pii pair<int,int>
#define ll long long
const int N=1e6+10;
const int mod=1e7+9;
const int maxn=0x3f3f3f3f;
const int minn=0xc0c0c0c0;
const int inf=99999999;
using namespace std;
struct edge
{
int next,to,w;
}a[N];
int head[30000]={0},len=0,dis[30000]={0},vis[30000]={0};
void add(int u,int v,int w)
{
a[++len]={head[u],v,w};
head[u]=len;
}
int main()
{
int t,r,p,s,i;
scanf("%d%d%d%d",&t,&r,&p,&s);
for(i=1;i<=r;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
add(b,a,c);
}
for(i=1;i<=p;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
}
for(i=1;i<=t;i++)
dis[i]=maxn;
dis[s]=0;
deque<int> q;
q.push_back(s);
vis[s]=1;
while(!q.empty())
{
int pre=q.front();
q.pop_front();
vis[pre]=0;
for(i=head[pre];i;i=a[i].next)
{
int v=a[i].to,w=a[i].w;
if(dis[v]>dis[pre]+w)
{
dis[v]=dis[pre]+w;
if(!vis[v])
{
vis[v]=1;
if(q.size() && dis[v]<dis[q.front()])
q.push_front(v);
else
q.push_back(v);
}
}
}
}
for(i=1;i<=t;i++)
if(dis[i]==maxn)
printf("NO PATH\n");
else
printf("%d\n",dis[i]);
return 0;
}