Tìm số ma sói tối đa - cần gợi ý :(

Đề bài Ma sói (Werewolf) là một trò chơi rất thịnh hành trong giới trẻ thành thị. Phiên bản Ma sói đơn giản nhất chỉ có hai vai (role): ban ngày ma sói đội lốt người sống trong làng, ban đêm hóa sói ăn thịt. Mỗi ngày làng họp lại chọn ra một “người” để bắt lại lưu đày hoang đảo vào buổi chiều.
Mỗi người chơi chỉ được buộc tội một người chơi khác là sói và sói không được buộc tội nhau. Hãy tìm số ma sói tối đa trong “ngày” hôm đó.

I/O

  • Input: stdin
    • Dòng đầu tiên là số người chơi 2 <= N <= 500000
    • N dòng tiếp theo: dòng thứ i gồm một số <= N nghĩa là người chơi thứ i chọn đó là ma sói.
  • Output: stdout
    • Một số duy nhất là số ma sói tối đa khả dĩ.

Ví dụ:
stdin
3
3
1
2
stdout
1
Số sói tối đa là N-1 vì cho dù tất cả buộc tội anh thì anh cũng phải vote người khác.
Giả sử người chơi 1 là sói. Người chơi 1 vote người số 3 là ma sói, vậy nếu người chơi 1 là sói thì người thứ 3 ko phải. Người chơi 2 buộc tội người 1 vậy người thứ 2 không phải là sói. Trong cả ba trường hợp đều chỉ có thể có 1 sói.

stdin
5
2
4
2
3
4
stdout
3
Nếu người chơi 1 là sói thì chỉ có người thứ 3 và 5, hoặc người thứ 4 là sói.
Nếu người chơi 2 là sói thì chỉ có người thứ 5 là sói.
Vậy kết quả là 3.

Giới hạn

  • 1/3 số điểm: N <= 15
  • 2/3 số điểm: N <= 2000

Lưu ý

  • Số ma sói có thể vượt quá hoặc bằng nửa số người chơi.
3 Likes

có test case không anh @rogp10 chứ thế này thì coi bộ khó hiểu quá T_T

4 Likes

Khó hiểu thật chứ, vì mình không biết trò này.
Có điều mình thắc mắc là điều kiện gì để xác định đó là ma sói dựa vào những lời buộc tội kia?

  • Người bị buộc tội nhiều nhất?
  • Những người không buộc tội lẫn nhau?

:thinking:

4 Likes

Anh đã thêm test case rồi :slight_smile:

Cái này ngoài lề rồi :smiley: bài này chỉ hỏi là số ma sói tối đa có thể thôi.

Werewolf

Nếu người chơi bị vote nhiều nhất thì sẽ bị “lưu đày” (tức là ra khỏi ván chơi và ngồi yên lặng). Để cho ván chơi ngắn đi thì mỗi lượt chơi sói sẽ ăn thịt một người.

6 Likes

thấy anh hỏi bài, e hết hồn

2 Likes

Đếm số vòng khép kín trong 1 đồ thị. Và số sói trong vòng = Math.floor(Node/2)

Như ở câu 1
image

Rõ ràng chỉ có 1 vòng, vòng này có 3 node -> Math.floor(3/2) = 1

Ở câu 2, ta thấy được chỉ có 1 vòng là 2 -> 4 -> 3 -> 2. 5 và 1 ko tạo 1 vòng nên coi 2 ng đó là sói, vì ko bị ai nghi ngờ. Và ta có được 1 vòng + 2 node -> Math.floor(3/2) + 1 + 1 = 3
image

Một edge case mình nghĩ ra là như sau. Khi đó vòng ko có sói.

Hoặc như thế này thì vòng chỉ có 1 sói
image

và thế này thì vòng vẫn đủ 2 sói
image

-> Có lẽ cần chăm chút công thức tính số sói trong vòng lại.


Vì 1 người buộc phải chỉ 1 ng khác, và người đó không phải chính mình, nên việc có loop hay 2 vòng chung 1 node sẽ không thể xảy ra :3
Và đồ thị sẽ luôn luôn có ít nhất 1 vòng

Việc đếm vòng này hình như có algo, và nó ko hẳn là “vòng” như mình nói ở trên. :thinking: Mà mình quên mất tên của nó rùi.

<(") Nhớ rồi, là đếm số thành phần liên thông (mạnh).

8 Likes

nếu A chọn B, B chọn C, vậy ta có cái graph như sau :V

A → B → C

ta có thể giả sử A là sói, vậy B ko phải là sói, C là sói, vậy ta có 2 sói trong mini graph trên. Nếu mini graph ko có cycle, thì số sói tối đa là ceil(V / 2.0) với V là số người trong mini graph :V

nếu trong mini graph có cycle:

A → B
 🡔 🡗
  C
A → B → C
 🡔     🡗
  E ← D

thì chỉ có 1 sói tối đa nếu có 2/3 người trong cycle, 2 sói tối đa nếu có 4/5 người trong cycle, hay số sói là floor(C / 2.0) với C là số sói trong cycle :V

nhiều mini graph khác :V :V

F → A → B ← C ← G
    ↑   ↓
    E ← D
F → A → B ← C
    ↑   ↓
    E ← D
F → A → B → C ← G
     🡔     🡗
      E ← D
        H
        ↓
F → A → B → C ← G
     🡔     🡗
      E ← D
        G
        ↓
F → A → B → C
     🡔     🡗
      E ← D
        H
        ↓
F → A → B → C ← G
     🡔     🡗
      E ← D
      ↑
      I

tổng quát ko biết thế nào :V :V :V

éc trễ hơn con rồng 3 phút :scream::scream::scream:

đồ thị có nhiều nhất 1 vòng vì mỗi người chỉ có 1 vote, ít nhất cái gì :V

nếu chiều dài nhánh đâm vào là chẵn thì ta coi như nhánh đó ko ảnh hưởng tới cycle
còn lại lặp 1 vòng quanh cái vòng lặp rồi đặt số 0 hoặc 1, nếu có nhánh đâm vào và chiều dài nhánh đó là lẻ thì đặt số 0, tiếp tục v.v… :V

        G
        ↓
F → A → B → C
     🡔     🡗
      E ← D

với graph như thế này thì chọn điểm bắt đầu lại phức tạp :V Nếu chọn điểm bắt đầu là A, B, C, E và chạy theo kiểu tham lam (cho là sói, nếu ko thể thì mới cho là người) thì vòng lặp có 2 sói (C và E). Nhưng nếu bắt đầu từ D thì cách tham lam chỉ có 1 sói D trong vòng lặp :V :V Như vậy nếu bắt đầu từ điểm X bất kì trong vòng lặp, ta phải giả sử 2 trường hợp X = sói và X = người mới đủ :V (với điều kiện giả sử số sói trong các nhánh đâm vào luôn là tối đa :V ví dụ hình trên thì F và G luôn là sói, A, B luôn là người, ko có vụ A sói F người. Lý luận là nếu cho sói trong vòng lặp thay vì trên nhánh, thì tổng số sói ko tăng ko giảm, nhưng sói trong vòng lặp lại loại trừ nhiều sói hơn, ví dụ A trong trường hợp trên sẽ loại F, B, E ko phải là sói, trong khi F chỉ loại A ko phải là sói, vậy chọn sói nằm trên nhánh sẽ “trừ” ít số sói hơn)

7 Likes

cách an toàn hơn lấy 1/3 số điểm với N <= 15 là duyệt trâu vì mỗi người chỉ có thể là người hoặc sói, 2 trường hợp, vậy N người có 2N trường hợp, N <= 15 thì duyệt trâu ngon lành :rofl:

4 Likes

Người i vote j (i != j) thì nếu i là sói thì j không phải, nếu j là sói thì i không phải, nên theo mình đồ thị này vô hướng và có thể có nhiều vòng.

2 Likes

nếu trong cùng 1 mini graph có nhiều vòng thì sẽ có 1 node có 2 nhánh out: 1 nhánh vô vòng lặp và 1 nhánh ra ngoài vòng lặp để kết nối với vòng lặp khác, điều này là ko thể vì 1 nhánh out tương đương với 1 vote, mà 1 người ko thể vote 2 lần :V

à mà đồ thị có hướng chứ sao vô hướng được :V A chọn B là sói đâu có tương đương với B chọn A là sói :V

edit: mà đúng là 1 mini graph lúc nào cũng có 1 cycle, vì node nào cũng có đúng 1 nhánh out, vậy ko có chuyện A --> B --> C vì C phải vote cho 1 ai đó, vậy là có ít nhất 1 vòng lặp :V Mà vì mỗi node chỉ có 1 nhánh out nên số vòng lặp tối đa cũng chỉ là 1 :V

3 Likes

Rồi nè, cách làm đơn giản <(")

Đầu tiên coi cái node lá đó, nó trỏ tới đâu. Thì gom 2 node đó tính là 1 sói và xóa 2 node đó khỏi đồ thị

Vd: 1 -> 2 -> 3 -> 2
Gom 1 -> 2 và xóa khỏi đồ thị, tính là 1 sói
-> còn mỗi node 3 lẻ loi, -> coi nó là sói luôn

Vì ta biết 1 là sói -> 2 phải là người. Nếu 2 là người -> 3 phải là sói để tăng số sói lên. Nên ta thoải mái xóa 1 và 2 và coi 3 là sói.

Cứ tìm và xóa như vậy, khi nào hết node lá thì thôi là ra kết quả cuối cùng <(")

Còn ko có node lá -> toàn là khép kín thì công thức mà táng thui

10 Likes

Like mạnh, cách này có lý nè :rofl:

3 Likes

Tương đương mà :slight_smile: vì kiểu gì thì hoặc A hoặc B là sói, hoặc cả hai đều là người.

4 Likes

A chọn B, B chọn C thì sao, đâu có nhánh B chọn A đâu :V

A --> B <–> C, D --> E <–> F, 2 vòng lặp, đâu có cách nào nối lại được
A chọn B
B chọn C
C chọn B
D chọn E
E chọn F
F chọn E
6 người đủ 6 vote rồi :V
A chọn B đâu có nghĩa là B chọn A :V
theo logic đề bài thì A chọn B hay B chọn A đều đồng nghĩa A hoặc B ko thể đồng thời là sói, nhưng cái đồ thị có biết đề bài đâu :V

5 Likes

Các thần đã bắt đầu trổ tài trong khi mình đang ngẫm lại luật chơi. :laughing:

4 Likes

vẽ lại cái đồ thị thì với bài này vô hướng hay có hướng gì chắc cũng xử lý được, nhưng vô hướng có lẽ kém “hiệu quả” hơn? :V Mỗi lần thêm 1 edge vào lại phải thêm 2 edge? :thinking:

4 Likes

Anh kém phần đồ thị mà :smiley:

3 Likes

nếu đồ thị có số đỉnh bằng số cạnh thì đồ thị có đúng 1 vòng lặp :V 1 vote = 1 cạnh, 1 người/sói = 1 đỉnh, 1 vote mỗi người thì số đỉnh bằng số cạnh đồ thị có đúng 1 vòng lặp :V

mà ko thấy đề cập thì tới đồ thì có hướng hay vô hướng :V

5 Likes

strongly connected hình như vô hướng cũng được mà :V Học lâu quá rồi giờ loạn tùng phèo cả lên =]]

1 Like

Vô hướng chắc rồi vì có hướng chỉ có weakly connected thôi chứ ko có connected: A <- B -> C <- A
connected = strong + weak nhưng số cạnh sẽ là 2n => toạch.

1 Like
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?