Các lượt nộp
    Danh sách bài
    Trang chủ
    Báo lỗi

    solution

    Đề bài: [Trình biên dịch] Cấp phát thanh ghi bằng tô màu đồ thị (Chaitin)

    Cấp phát thanh ghi (register allocation) bằng tô màu đồ thị giao (interference graph coloring) là kỹ thuật tối ưu cốt lõi ở giai đoạn sinh mã: các biến tạm (temporary) xung đột (cùng "sống" tại một thời điểm) không được cấp cùng một thanh ghi. Bài này yêu cầu cài đặt thuật toán simplify/select đơn giản hoá của Chaitin.

    Cho đồ thị giao gồm nnn biến tạm (đánh số 0,…,n−10, \ldots, n-10,…,n−1), mmm cạnh xung đột, và kkk thanh ghi khả dụng (đánh số 0,…,k−10, \ldots, k-10,…,k−1). Thực hiện hai giai đoạn sau:

    Giai đoạn 1 — Đơn giản hoá (simplify), lặp cho tới khi đồ thị (phần còn lại) rỗng:

    • Xét các đỉnh còn lại trong đồ thị và bậc (số cạnh nối tới các đỉnh còn lại) của chúng.
    • Nếu tồn tại (các) đỉnh còn lại có bậc nhỏ hơn kkk: chọn đỉnh có chỉ số nhỏ nhất trong số đó, loại khỏi đồ thị (cùng các cạnh liên quan) và đẩy vào một ngăn xếp SSS.
    • Nếu không còn đỉnh nào có bậc nhỏ hơn kkk (mọi đỉnh còn lại đều có bậc ≥k\ge k≥k): chọn đỉnh có bậc lớn nhất; nếu có nhiều đỉnh cùng đạt bậc lớn nhất, chọn đỉnh có chỉ số nhỏ nhất trong số đó (đây là ứng viên tràn thanh ghi — potential spill); loại khỏi đồ thị và đẩy vào SSS.

    Giai đoạn 2 — Tô màu (select): rút các đỉnh ra khỏi SSS theo thứ tự ngược lại với thứ tự đã đẩy vào (đỉnh đẩy vào sau cùng được tô màu đầu tiên). Với mỗi đỉnh vvv được rút ra, xét tập màu đã dùng bởi các đỉnh kề với vvv trong đồ thị gốc mà đã được tô màu (tính đến thời điểm này); gán cho vvv màu nhỏ nhất trong {0,…,k−1}\{0, \ldots, k-1\}{0,…,k−1} chưa bị các đỉnh kề đã tô dùng. Nếu cả kkk màu đều đã bị dùng bởi các đỉnh kề đã tô, đỉnh vvv bị tràn thanh ghi (SPILL) — không có thanh ghi nào được gán.

    Ví dụ: đồ thị tam giác (3 đỉnh, 3 cạnh đôi một xung đột) với k=2k=2k=2: không đủ 2 thanh ghi để tô 3 đỉnh xung đột đôi một, nên đúng một đỉnh sẽ bị SPILL, hai đỉnh còn lại nhận hai thanh ghi khác nhau.

    • Định dạng đầu vào:

      Dòng đầu tiên chứa ba số nguyên nnn, mmm, kkk (1≤n≤3001 \le n \le 3001≤n≤300, 0≤m≤200000 \le m \le 200000≤m≤20000, 1≤k≤n1 \le k \le n1≤k≤n).

      mmm dòng tiếp theo, mỗi dòng hai số nguyên uuu, vvv (0≤u,v<n0 \le u, v < n0≤u,v<n, u≠vu \ne vu=v) — nghĩa là biến tạm uuu và vvv xung đột. Có thể có cạnh lặp lại, không ảnh hưởng tới kết quả.

    • Định dạng đầu ra:

      In ra nnn dòng: dòng thứ iii (ứng với biến tạm i−1i-1i−1, i=1,…,ni = 1, \ldots, ni=1,…,n) chứa số hiệu thanh ghi (0,…,k−10, \ldots, k-10,…,k−1) được gán cho biến đó theo thuật toán trên, hoặc chuỗi SPILL nếu biến đó bị tràn thanh ghi.

    Ví dụ:

    Đầu vào:

    3 3 2
    0 1
    1 2
    0 2
    

    Đầu ra:

    SPILL
    1
    0
    

    Đầu vào:

    1 0 1
    

    Đầu ra:

    0
    

    Đang tải editor...