第一直觉是tarjan缩点+拓扑,但是不知道如何下手(据说正解就是这个)
然后画了个图,发现,好像是个单源最短路!因为有单向边,所以一些点去不了,所以输出判dis就行
然后!!!它TLE了!!!
加优化,SLF和LLL优化,专氪网格图
代码
//By AcerMo
#include<cmath>
#include<deque>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int M=30050;
struct edge{int to,cost;}add;
vector<edge>v[M];
int n,m1,m2,st;
int dis[M],vis[M];
inline int read()
{
int x=0,f=1;char ch=getchar();
while (ch>'9'||ch<'0') {if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
inline void SPFA()
{
fill(dis,dis+n+1,M*30);
deque<int>q;dis[st]=0;q.push_front(st);
while (q.size())
{
int u=q.front();q.pop_front();vis[u]=0;
for (int i=0;i<v[u].size();i++)
{
int go=v[u][i].to;
int pay=v[u][i].cost;
if (dis[go]>dis[u]+pay)
{
dis[go]=dis[u]+pay;
if (!vis[go])
{
if (q.empty()||dis[go]>dis[q.front()]) q.push_back(go),vis[go]=1;
else q.push_front(go),vis[go]=1;
}
}
}
}
return ;
}
signed main()
{
n=read();m1=read();m2=read();st=read();
for (int i=1;i<=m1;i++)
{
int x=read(),y=read(),z=read();
add.to=y;add.cost=z;v[x].push_back(add);
add.to=x;add.cost=z;v[y].push_back(add);
}
for (int i=1;i<=m2;i++)
{
int x=read();add.to=read();add.cost=read();v[x].push_back(add);
}
SPFA();
for (int i=1;i<=n;i++)
if (dis[i]<M*30) cout<<dis[i]<<endl;
else puts("NO PATH");
return 0;
}