เดินทางแบบ xor

o61_may06_superxor

กำหนดให้

  • CC เป็นเซตของ cycle ทั้งหมดในกราฟที่โจทย์กำหนดให้
  • wpw_p คือแต้มที่ได้จากการเดินบน path pp สำหรับ path pp จาก node uu ไป vv ใด ๆ (อาจเขียนเป็น wuvw_{u \to v} แทน wpw_p ได้)

Observation 1

หากมี path จาก node ss ไป node tt หนึ่งเส้นทางเรียกว่า pp เราสามารถเติม cycle cCc \in C ใด ๆ เข้าไปใน path นี้โดยแต้มจะเท่ากับ wpwcw_p\oplus w_c เสมอ

ให้ uu เป็น node หนึ่งที่อยู่ใน pp และ vv เป็น node หนึ่งที่อยู่ใน cc เราสามารถเดินทางจาก ss ไป tt ได้โดย

  1. เดินทางบน path จาก ss ไป uu
  2. เดินทางบน path จาก uu ไป vv (มีเสมอเนื่องจากโจทย์รับประกันว่าเป็น connected graph)
  3. เดินทางบน cycle cc จนกว่าจะวนกลับมาที่ vv อีกครั้ง
  4. เดินทางบน path จาก vv ไป uu
  5. เดินทางบน path จาก uu ไป tt

เนื่องจากแต้มที่ได้จากการเดินทางคำนวณจาก XOR ของน้ำหนักเส้นเชื่อมทั้งหมดที่เดินผ่าน ขั้นตอนที่ 2 และ 4 จะหักล้างกัน เปรียบเสมือนว่ามีเพียงแค่ wpw_p และ wcw_c ที่นำมาคิดเป็นแต้มรวมเท่านั้น

หาก pp และ cc ไม่มีเส้นเชื่อมซ้ำกันเลยจะเห็นได้ชัดเจนว่าแต้มรวมย่อมเท่ากับ wpwcw_p \oplus w_c

กรณีที่มีเส้นเชื่อมซ้ำกัน การเดินบน cycle จะมีผลเปรียบเสมือนการเปลี่ยน path ตั้งต้น เช่น หาก pp คือ 123451 \to 2 \to 3 \to 4 \to 5 และ cc คือ 2674322 \to 6 \to 7 \to 4 \to 3 \to 2 เมื่อนำมาผสมกันเป็น 12774323451 \to 2 \to 7 \to 7 \to 4 \to 3 \to 2 \to 3 \to 4 \to 5 จะเปรียบเสมือนการเดินทางบน 1267451 \to 2 \to 6 \to 7 \to 4 \to 5 โดยตรง

จากข้อสังเกตนี้ เราสามารถสรุปได้ว่า เราสามารถสร้าง path จาก ss ไป tt ทุก path ที่เป็นไปได้ โดยใช้ path ตั้งต้นเพียง path เดียวเท่านั้นแล้วเติม cycle ตามความเหมาะสม

หากเราเลือก cycle ดี ๆ เราสามารถสร้าง path จาก ss ไป tt ให้ได้แต้มรวมมากสุด

Observation 2

บาง cycle ในกราฟสามารถสร้างได้จากการนำ cycle อื่นอย่างน้อย 2 cycle มาผสมกัน เช่น cycle 12311 \to 2 \to 3 \to 1 เมื่อนำมาผสมกับ 23422 \to 3 \to 4 \to 2 จะได้เป็น 124311 \to 2 \to 4 \to 3 \to 1 เพราะเส้นเชื่อมระหว่าง 22 กับ 33 ถูกหักล้างจากการเดินทางซ้ำสองครั้ง

ดังนั้น เราสามารถตัดบาง cycle ออกจากเซต CC ได้โดยไม่สูญเสียอิสระในการเติม cycle ให้ path ตามที่กล่าวในหัวข้อก่อนหน้า

เรียกเซตที่เล็กที่สุดที่เราสามารถนำสมาชิกมารวมกันแล้วสามารถสร้างทุก cCc \in C ได้ว่า basis ของ CC หรือ fundamental cycle set โดยในที่นี้เราจะใช้สัญลักษณ์ CC^*

วิธีสร้าง CC^* ที่ง่ายที่สุดคือการ Depth-first Search ออกจาก node หนึ่งในกราฟ (สมมุติว่า node rr) จะได้ tree edge เป็นเส้นที่จะใช้ใน path ตั้งต้นระหว่างคู่ node ใด ๆ และ back edge ทั้งหมดเป็นเส้นที่ใช้ในการสร้าง fundamental cycle set (เส้นที่เชื่อมระหว่าง uu กับ vv จะทำให้เกิด cycle urvuu \to r \to v \to u)

เพื่อความสะดวกในการคำนวณต่อจากนี้ ระหว่าง Depth-first Search ให้สร้าง array ไว้เพื่อเก็บค่าของ wruw_{r \to u} สำหรับทุก node uu

นอกจากนี้ สำหรับแต่ละ back edge ที่เชื่อมระหว่าง uu และ vv ให้เก็บแต้มที่ได้จากการเดินบน cycle นั้น คำนวณได้จาก wruwrvwuvw_{r \to u} \oplus w_{r \to v} \oplus w_{u \to v} (สองพจน์แรกได้จากที่คำนวณไว้ย่อหน้าก่อนหน้า พจน์สุดท้ายคือน้ำหนักของเส้นเชื่อมระหว่าง uu กับ vv)

Observation 3

ในการหา path ที่ได้แต้มมากที่สุดจาก ss ไป tt เราสามารถหา path ตั้งต้น (เรียกว่า pp) ได้โดยเดินทางจาก ss ไป rr และจาก rr ไป tt ทำให้ได้ wp=wruwrvw_p = w_{r\to u} \oplus w_{r \to v}

การเลือกเติม cycle cCc \in C^* ต่าง ๆ เข้าไปทำให้แต้มเปลี่ยน เนื่องจากเราไม่ได้สนใจว่าเติม node อะไรเข้าไปบ้างกันแน่ ต่อไปนี้ จะมองว่า CC^* เป็นเซตของจำนวนเต็มที่เราสามารถนำไป XOR เพื่อสร้างคำตอบได้

เช่นเดียวกับ Observation 2 ค่า cCc \in C^* บางค่าอาจจะตัดออกได้เพราะสามารถสร้างจากค่าอื่น ๆ ใน CC^* ได้ เช่น หาก C={112,1012,1102}C^* = \{11_2, 101_2, 110_2\} สามารถตัด 1012101_2 ออกได้เพราะ 1012=1121102101_2 = 11_2 \oplus 110_2 (หรือตัดตัวอื่นก็ได้)

กำหนดให้ CC^{**} แทนเซตที่เล็กที่สุดที่เป็น basis ของ CC^*

เราสามารถหา CC^{**} ได้โดยใช้ขั้นตอนวิธี Gaussian Elimination โดยให้แต่ละแถวของเมทริกซ์แทนเลขแต่ละ cycle และแต่ละคอลัมน์แทนแต่ละ bit ของเลขดังกล่าว

เนื่องจากโจทย์รับประกันว่า 0c26310 \leq c \leq 2^{63}-1 ดังนั้นเมทริกซ์จะมีทั้งหมด 6363 คอลัมน์

สุดท้ายแล้ว เราจะได้ basis ที่ประกอบไปด้วยตัวเลขไม่เกิน 6363 ตัว โดยที่ตัวเลขแต่ละตัวจะมี most significant digit ต่างกันทั้งหมด

สำหรับ query การเดินจาก ss ไป tt สามารถหาแต้มรวมมากสุดที่เป็นไปได้โดยกำหนดให้ ans=wruwrvans = w_{r\to u} \oplus w_{r \to v} แล้วตัดสินใจว่าจะนำสมาชิกแต่ละตัวใน CC^{**} มา XOR หรือไม่ โดยตัดสินใจตั้งแต่ตัวเลขที่มากที่สุดมายังตัวเลขที่น้อยที่สุดแบบ greedy (หากนำมา XOR แล้วได้คำตอบดีขึ้นให้ XOR ทันที)