[CF1161F]Zigzag Game

通过这道模板题学了一种新的模型,记录一下。

稳定婚姻匹配

至于这道题,显然是一个二分图博弈的模型。考虑选择Bob,我们要找一组匹配使得任何情况下Bob都有匹配边能走。不失一般性假设Alice选择了increase,起点选在左侧,那么一组匹配合法当且仅当不存在匹配((i,j),(k,l))使得(w_{i,j}<w_{j,k}<w_{k,l})。令左到右的权值为原边权,右到左的权值为原边权的相反数,用链接内的算法一定能找到完美匹配。

#include<bits/stdc++.h>
using namespace std;


int gi() {
    int x = 0, o = 1;
    char ch = getchar();
    while((ch < '0' || ch > '9') && ch != '-') {
        ch = getchar();
    }
    if(ch == '-') {
        o = -1, ch = getchar();
    }
    while(ch >= '0' && ch <= '9') {
        x = x * 10 + ch - '0', ch = getchar();
    }
    return x * o;
}

int n, a[60][60], p[110], v[60], x;
vector<int> E[60];

bool cmp(int x, int y) {
    return v[x] > v[y];
}
int main() {
    int T = gi();
    while(T--) {
        n = gi();
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++) {
                a[i][j] = gi();
            }
        cout << "B
", cout.flush();
        if((getchar() == 'D') ^ ((x = gi()) > n))
            for(int i = 1; i <= n; i++)
                for(int j = 1; j <= n; j++) {
                    a[i][j] = -a[i][j];
                }

        memset(p, 0, sizeof(p));
        for(int i = 1; i <= n; i++) {
            E[i].resize(n);
            for(int j = 1; j <= n; j++) {
                v[j] = a[i][j], E[i][j - 1] = j;
            }
            sort(E[i].begin(), E[i].end(), cmp);
        }
        int m = n;
        while(m)
            for(int i = 1, j; i <= n; i++)
                if(!p[i])
                    while(1) {
                        j = E[i].back(), E[i].pop_back();
                        if(!p[j + n]) {
                            p[i] = j + n;
                            p[j + n] = i;
                            --m;
                            break;
                        } else if(a[i][j] > a[p[j + n]][j]) {
                            p[p[j + n]] = 0;
                            p[i] = j + n;
                            p[j + n] = i;
                            break;
                        }
                    }
        while(1) {
            cout << p[x] << '
';
            cout.flush();
            x = gi();
            if(x < 0) {
                break;
            }
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/gczdajuruo/p/10822172.html