前言
处理负权
传送门 :
思路
因为有负权 所以我们无法使用 dij
因此我们考虑 s p f a spfa spfa 但是这题 中 等 中等 中等 不是盖的
所以我们需要优化
SLF
我们可以采用双端队列优化
每次对于 d i s t [ x . t o ] > d i s t [ t ] + x . v a l dist[x.to]>dist[t]+x.val dist[x.to]>dist[t]+x.val
-
如果当前的点 小于 队头
那么我们让他加入队头 -
如果当前的点 大于 队头
那么我们让他加入队尾
CODE
#include <bits/stdc++.h>
using namespace std;
const int N = 3e4+10;
int n,r,p,s;
int dist[N],st[N];
struct Edge
{
int to,val;
};
vector<Edge> g[N];
void spfa(int s)
{
memset(dist,0x3f,sizeof dist);
deque<int> q;
dist[s] = 0;
st[s] =1;
q.push_back(s);
while(!q.empty())
{
//cout<<"?"<<endl;
int t = q.front();
st[t] = 0;
q.pop_front();
for(auto x : g[t])
{
if(dist[x.to]>dist[t]+x.val)
{
dist[x.to] = dist[t]+x.val;
if(!st[x.to])
{
st[x.to] =1;
if(q.size() && dist[x.to]<dist[q.front()])
q.push_front(x.to);
else
q.push_back(x.to);
}
}
}
}
}
void solve()
{
cin>>n>>r>>p>>s;
while(r -- )
{
int a,b,c;
cin>>a>>b>>c;
g[a].push_back({b,c});
g[b].push_back({a,c});
}
while(p -- )
{
int a,b,c;
cin>>a>>b>>c;
g[a].push_back({b,c});
}
spfa(s);
for(int i=1;i<=n;i++)
{
if(dist[i] == 0x3f3f3f3f)
cout<<"NO PATH"<<endl;
else
cout<<dist[i]<<endl;
}
}
int main()
{
ios::sync_with_stdio(false);
solve();
return 0;
}
DIJ 优化 大概思路
我们可以让 所有的 只含有 无向边的连通块 看成一个整体
然后我们可以对这多个连通块 求一遍 拓扑序即可