Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use std::io::BufRead;
- #[derive(Default)]
- struct Vertex {
- first_edge: usize,
- first_reverse_edge: usize,
- max_distance: Option<i64>,
- }
- #[derive(Default)]
- struct Edge {
- start: usize,
- end: usize,
- next: usize,
- next_reverse: usize,
- weight: i64,
- useful: bool,
- }
- struct Searcher {
- n: usize,
- vertices: Vec<Vertex>,
- edges: Vec<Edge>,
- visited: Vec<Option<i64>>,
- high_score: i64,
- }
- impl Searcher {
- // marks all edges that can reach node N?
- fn mark_useful_edges(&mut self, visited: &mut [bool], i: usize) {
- visited[i] = true;
- let mut k = self.vertices[i].first_reverse_edge;
- while k != 0 {
- self.edges[k].useful = true;
- let j = self.edges[k].start;
- if !visited[j] {
- self.mark_useful_edges(visited, j);
- }
- k = self.edges[k].next_reverse;
- }
- }
- fn search(&mut self, i: usize, w: i64) -> Result<i64, ()> {
- let mut d = std::i64::MIN;
- if i == self.n {
- if self.high_score < w {
- self.high_score = w;
- }
- d = 0;
- }
- let mut k = self.vertices[i].first_edge;
- while k != 0 {
- if self.edges[k].useful {
- let j = self.edges[k].end;
- let w1 = self.edges[k].weight;
- if let Some(w2) = self.visited[j] {
- if w2 < w + w1 {
- return Err(());
- }
- } else {
- self.visited[j] = Some(w + w1);
- let d1 = if let Some(d1) = self.vertices[j].max_distance {
- d1
- } else {
- self.search(j, w + w1)?
- };
- if d1 != std::i64::MIN {
- d = d.max(w1 + d1);
- }
- self.visited[j] = None;
- }
- }
- k = self.edges[k].next;
- }
- self.vertices[i].max_distance = Some(d);
- Ok(d)
- }
- }
- fn main() {
- let stdin = std::io::stdin();
- let mut stdin = stdin.lock();
- let mut input = String::with_capacity(32);
- stdin.read_line(&mut input).unwrap();
- let mut i = input.trim_end().split(' ');
- let n: usize = i.next().unwrap().parse().unwrap();
- let m: usize = i.next().unwrap().parse().unwrap();
- let mut v = Vec::new();
- v.resize_with(n + 1, Vertex::default);
- let mut e = Vec::with_capacity(m + 1);
- e.push(Edge::default());
- for k in 1..=m {
- input.clear();
- stdin.read_line(&mut input).unwrap();
- let mut i = input.trim_end().split(' ');
- let a: usize = i.next().unwrap().parse().unwrap();
- let b: usize = i.next().unwrap().parse().unwrap();
- let w: i64 = i.next().unwrap().parse().unwrap();
- e.push(Edge {
- start: a,
- end: b,
- next: v[a].first_edge,
- next_reverse: v[b].first_reverse_edge,
- weight: w,
- useful: false,
- });
- v[a].first_edge = k;
- v[b].first_reverse_edge = k;
- }
- let mut visited = Vec::new();
- visited.resize(n + 1, None);
- visited[1] = Some(0);
- let mut searcher = Searcher {
- n,
- vertices: v,
- edges: e,
- visited,
- high_score: std::i64::MIN,
- };
- {
- let mut visited = Vec::new();
- visited.resize(n + 1, false);
- searcher.mark_useful_edges(&mut visited, n);
- }
- if let Ok(d) = searcher.search(1, 0) {
- println!("{}", d);
- } else {
- println!("-1");
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement