/**\
最短路模板
输入: n m s t 接下来m行 u, v, w表示u -> v 有一条权值为w的无向边
input:
3 3 1 2
1 2 3
2 3 4
1 3 5
output:
3
\**/
#include
using namespace std;
#define fi first
#define se second
#define go continue
#define int long long
#define PII pair
#define sf(x) scanf("%lld",&x)
#define ytz int _; sf(_); while(_--)
#define fory(i,a,b) for(int i = a; i <= b; ++i)
#define forl(i,a,b) for(int i = a; i >= b; --i)
#define debug(a) cout << #a << " = " << a <const int N = 1e5 + 10;
struct node
{
int to, w, next;
} e[N << 1];
int cnt = 0, head[N];
inline void add_edge(int u, int v, int w)
{
e[++cnt].to = v;
e[cnt].w = w;
e[cnt].next = head[u];
head[u] = cnt;
}
inline void init()
{
cnt = 0;
memset(head, -1, sizeof head);
}
int n, m, s, t;
struct v
{
int x, dis;
bool operator < (const v& a) const
{
return dis > a.dis; //stl默认大顶堆
}
};
int dis[N];
bool vis[N];
/**\
dijstra
1、从源点开始每次选取一个离点集距离最近的点t 添加到集合中
2、利用t点对集合中的点进行松弛操作,进行更新
3、使用堆进行1找点的操作降低时间复杂度
4、不能在有负边权的图中使用
\**/
inline void dijstra(int s, int t)
{
priority_queue q;
memset(dis, 0x3f, sizeof dis);
memset(vis, 0, sizeof vis);
dis[s] = 0;
q.push({s, 0});
while(!q.empty())
{
v now = q.top();
q.pop();
if(vis[now.x]) go;
vis[now.x] = 1;
for(int i = head[now.x] ; i != -1; i = e[i].next)
{
int y = e[i].to;
if(vis[y]) go;
if(dis[y] > dis[now.x] + e[i].w)
{
dis[y] = dis[now.x] + e[i].w;
q.push({y, dis[y]});
}
}
}
if(dis[t] > 0x3f3f3f3f) cout << -1;
else cout << dis[t];
}
/**\
spfa算法思路:
1、每次迭代,取出队头点v,依次枚举从v出发的边,v->u,设边的长度为w
判断dis[v] + w 是否小于dis[u], 小于则更新值,
2、由于s-u的距离变短了,有可能u能改变其他点,使用vis数组判断是否在队列,没有则放入
3、若一个点的入队次数超过n,则存在负环
\**/
queue<int> q1;
inline void spfa(int s, int t)
{
memset(dis, 0x3f, sizeof dis);
memset(vis, 0, sizeof vis);
dis[s] = 0;
vis[s] = 1;
q1.push(s);
while(!q1.empty())
{
int x = q1.front();
q1.pop();
vis[x] = 0;
for(int i = head[x]; i != -1; i = e[i].next)
{
int y = e[i].to;
if(dis[y] > dis[x] + e[i].w)
{
dis[y] = dis[x] + e[i].w;
if(!vis[y])
{
q1.push(y);
vis[y] = 1;
}
}
}
}
if(dis[t] >= 0x3f3f3f3f) cout << -1;
else cout << dis[t];
}
inline void solve()
{
init();
sf(n), sf(m), sf(s), sf(t);
fory(i, 1, m)
{
int x, y, z;
sf(x), sf(y), sf(z);
add_edge(x, y, z);
add_edge(y, x, z);
}
//dijstra(s, t);
spfa(s, t);
}
signed main()
{
solve();
return 0;
}