CSES 1673 High Score

題目

https://cses.fi/problemset/task/1673

Solution

用Bellman Ford找出11到每個點的最長路徑(邊權改成負的後的最短路徑),然後用dfs檢查路徑上是否有存在負環的點,如果有的話就直接輸出1-1,如果沒有就輸出1n1\to n的最短距離。

dfs檢查的部分,如果在Bellman Ford的第nn次還有被修改到的話,那這個點就是負環上的點。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <bits/stdc++.h>
#pragma GCC optimize("Ofast,unroll-loops,no-stack-protector,fast-math")
#pragma GCC target("abm,bmi,bmi2,mmx,sse,sse2,sse3,ssse3,sse4,popcnt,avx,avx2,fma,tune=native")
#pragma comment(linker, "/stack:200000000")
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define int long long
#define pb push_back
#define endl '\n'
#define F first
#define S second
using namespace std;
const int N = 2e5+5,mod = 998244353,inf = 1e15+7;
typedef pair<int,int> pii;
vector<pii>g2[N];
vector<tuple<int,int,int>>e;
int dis[N] = {},cnt[N] = {},vis[N] = {},path[N] = {};
int n,m,idx = 0;
void dfs(int u){
if(cnt[u]>=n){
cout<< -1<<endl;
exit(0);
}
for(auto [v,w]:g2[u]){
if(vis[v]==0){
vis[v] = 1;
dfs(v);
}
}
}
bool spfa(){
for(int i = 1;i<=n;++i){
dis[i] = inf;
}
dis[1] = 0;
for(int i = 1;i<=n;++i){
for(auto [u,v,w]:e){
if(dis[u]<inf and dis[v]>dis[u]+w){
dis[v] = dis[u]+w;
cnt[v] = i;
}
}
}
dfs(n);
return 1;
}
signed main(){
IOS;
cin>>n>>m;
for(int i = 0;i<m;++i){
int u,v,w;
cin>>u>>v>>w;
e.pb({u,v,-w});
g2[v].pb({u,-w});
}
if(spfa()==0 or dis[n]==inf){
cout<< -1<<endl;
}
else{
cout<< -dis[n]<<endl;
}
}