COCI 2019/2020 - Contest 5 - Putovanje

Xem dạng PDF

Gửi bài giải

Điểm: 1,30 (OI)
Giới hạn thời gian: 1.0s
Giới hạn bộ nhớ: 512M
Input: stdin
Output: stdout

Người đăng:
Nguồn bài:
COCI 2019/2020 - Contest 5
Dạng bài
Ngôn ngữ cho phép
C, C++, Go, Java, Kotlin, Pascal, PyPy, Python, Rust, Scratch

Chàng Fabijan rất thích đi bar và đi du lịch. Anh ấy mong muốn rằng mình có thể được trải nghiệm beer cà phê ở tất cả các thị trấn tại quốc gia của mình. Có ~N~ thị trấn được đánh số từ ~1~ đến ~N~. Các thị trấn được nối với nhau bằng các tuyến đường hai chiều. Có tất cả ~(N-1)~ con đường hai chiều sao cho từ một thị trấn ta có thể đi đến bất kì thị trấn khác bằng cách đi qua một số con đường.

Fabijan đã quyết định sẽ lên đường để trải nghiệm tất cả cà phê tại các thị trấn theo thứ tự từ ~1~ đến ~N~. Anh ấy khởi đầu tại thị trấn có số thứ tự là ~1~ (nơi mà anh ấy đã uống cốc cà phê đầu tiên) và sẽ hướng đến thị trấn số ~2~ để trải nghiệm cốc cà phê tiếp theo. Trên đường đi đến thị trấn tiếp theo Fabijan có thể đi qua một số thị trấn khác nhau nhưng anh ấy sẽ chỉ dừng lại khi đến được thị trấn thứ ~2~. Sau khi đến được thị trấn thứ ~2~, anh ta sẽ lại tiếp tục đi cho đến khi đến được thị trấn thứ ~3~, cứ như vậy cho đến khi anh ấy đến được thị trấn ~N~ và thưởng thức tách cà phê cuối cùng.

Tuy nhiên, để vượt qua được những con đường, Fabijan sẽ cần có những tấm vé thông hành. Để đi qua một con đường ~i~, Fabijan có thể lựa chọn một trong hai cách:

  • Cách 1: mua vé dùng một lần giá ~C_{i1}~ euro để đi qua con đường đó một lần.
  • Cách 2: mua vé dùng nhiều lần giá ~C_{i2}~ euro một lần duy nhất và khi gặp lại con đường đó sẽ không cần mua vé nữa.

Hãy viết chương trình xác định số tiền nhỏ nhất mà Fabijan phải bỏ ra để hoàn thành chuyến đi của mình.

Input

  • Dòng đầu chứa số nguyên ~N~ (~2 \leq N \leq 200000~).
  • ~(N-1)~ dòng tiếp theo mỗi dòng gồm 4 số nguyên ~A_i~ ~B_i~ ~C_{i1}~ ~C_{i2}~ ~(1 \leq A_i, B_i \leq N, 1 \leq C_{i1} \leq C_{i2} \leq 100000 )~ biểu diễn một đường đi giữa hai thành phố ~A_i~ và ~B_i~ với giá vé dùng một lần là ~C_{i1}~ và giá vé dùng nhiều lần là ~C_{i2}~.

Output

  • Số tiền nhỏ nhất mà Fabijan phải bỏ ra cho chuyến đi

Sample 1

Input
4
1 2 3 5
1 3 2 4
2 4 1 3
Output
10

Sample 2

Input
4
1 4 5 5
3 4 4 7
2 4 2 6
Output
16

Sample 3

Input
5
1 2 2 3
1 3 2 3
1 4 2 3
1 5 2 3
Output
11

Subtask

  • ~9~ test có ~2 \leq N \leq 2000~
  • ~12~ test tiếp theo mỗi thị trấn sẽ được kết nối trực tiếp với nhiều nhất hai thị trấn khác.
  • ~10~ test còn lại không có điều kiện gì thêm

Giải thích ví dụ thứ nhất

Ta mô tả chuyến đi của Fabijan như sau:

  • Đi từ thị trấn 1 đến thị trấn 2: mua vé dùng nhiều lần (5 euro).
  • Đi từ thị trấn 2 sang thị trấn 3: từ thị trấn 2 quay về thị trấn 1 (không mất phí vì đã mua vé dùng nhiều lần) rồi mua vé dùng một lần từ thị trấn 1 sang thị trấn 3 (2 euro).
  • Đi từ thị trấn 3 đến thị trấn 4: từ thị trấn 3 mua vé dùng một lần để đến thị trấn 1 (2 euro) rồi sang thị trấn 2 (không mất phí vì đã mua vé dùng nhiều lần) và mua vé dùng một lần sang thị trấn 4 (1 euro)

Tổng số tiền mà Fabijan bỏ ra là 5 + 2 + 2 + 1 = 10


Bình luận

Hãy đọc nội quy trước khi bình luận.



  • 0
    minhkochamhoc  đã bình luận lúc 16, Tháng 6, 2025, 10:01

    solve:

    tóm tắt và giải thích đề :

    ta có 1 đồ thị dạng cây n đỉnh n-1 cạnh , mỗi cạnh sẽ mang 2 trọng số là c1 và c2 với ý nghĩa nếu ta muốn đi qua cạnh đó ta có thể mua mất chi phí là c1 nếu chỉ đi 1 lần , còn nếu muốn đi vô hạn lần ta có thể sử dụng vé có giá trị c2 . ban đầu ta ở đỉnh 1 , ta có 1 hành trình cần phải hoàn thành là đi từ đỉnh 1->2,2->3,3->4,..... n-1 -> n. đề yêu cầu ta phải sử dụng hợp lý quyền lựa chọn di chuyển khi đi qua mỗi cạnh sao cho chi phí của toàn bộ hành trình của ta là nhỏ nhất.

    suy luận :

    • để đánh giá xem với mỗi con đường ta cần mua vé thông hành 1 lần hay vô hạn lần rõ ràng ta cần biết được số lần ta cần phải đi qua cạnh đó để hoàn thành hành trình của mình , vậy gọi x là số lần ta đã di chuyển qua cạnh đó khi kết thúc hành trình , từ đó ta đưa ra kết quả bằng cách xét hết tất cả các cạnh rồi chọn ra giá trị nhỏ hơn từ biểu thức min(x*c1,c2) để biết được chi phí nhỏ nhất cho suốt hành trình này.
    • từ nhận xét trên ta thấy rằng chỉ cần tính được toàn bộ x của tất cả các cạnh trên đồ thị ta sẽ có thể đưa ra được kết quả bài tập

    ý tưởng:

    • vậy ta sẽ có 3 cách giải bài tập trên : LCA , DSU on tree , LCA + Difference‑on‑Tree (cách này cx na ná cách LCA kia)
    • mình sẽ hướng dẫn cách sử dụng LCA bình thường vì mình thấy nó dễ tiếp cận nhất : gọi cnt[u] là số lần ta di chuyển qua cạnh nối giữa u và cha của u (1 cha có thể có nhiều con nhưng 1 con sẽ chỉ có 1 cha nên chắc chắn ko có cạnh nào trùng). ta sử dụng thuật toán LCA để tìm tổ tiên giữa các cặp {1,2},{2,3},{3,4},....{n-1,n} , giả sử xét 1 cặp {u,v} gọi tổ tiên chung ta tìm được là w vì ta phải di chuyển từ u->w->v nên tất cả những cạnh trên đường đi này đều được cộng thêm 1 lần đi qua , từ đó ta có cách tính nhanh như sau : cnt[u]++,cnt[v]++,cnt[w]-=2 ( vì ta chỉ đi tới đỉnh w chứ ko đi lên tổ tiên của w nên ta sẽ tính như vậy để sau khôi phục cả cây nó sẽ ko gây sai xót vì ta theo định nghĩa đã gọi cnt mà ) . sau khi đã thực hiện cách tính trên với toàn bộ các cặp đường đi ta sẽ sử dụng DFS để đi tới lá và khôi phục từ lá đổ lên để tính kết quả.
    • code của mình hehehe

    chúc bạn may mắn 🍀 , kết quả của bạn đang tới rất gần rồi đừng bỏ cuộc nhé 💪


  • 4
    Free_De_La_Zenith  đã bình luận lúc 5, Tháng 6, 2025, 9:26

    Spoil

    bài này có 2 cách

    ! C1:LCA C2:DSU


  • -4
    nhan19042007  đã bình luận lúc 18, Tháng 10, 2024, 0:54

    ggez