稳定婚姻 uoj41 清华集训2014 矩阵变换

http://uoj.ac/problem/41

稳定婚姻问题简单的说就是

男的不停求婚女的不停拒绝

然后都选择当且最喜欢的作为pair

本题的话把行,数字看成男女

行喜欢本行中靠左的

数字喜欢在所有行出现位置最靠右的行

观察如下的情况

i: xxxxxxxxxxxxx

j: x vvvv

此时不合法

因为j-x喜欢的程度大于i-x

复杂度\(O(nmT)\)

#include <bits/stdc++.h>
#define fo(i, n) for(int i = 1; i <= (n); i ++)
#define out(x) cerr << #x << " = " << x << "\n"
using namespace std;
// by piano
template<typename tp> inline void read(tp &x) {
  x = 0; char c = getchar(); bool f = 0;
  for(; c < '0' || c > '9'; f |= (c == '-'), c = getchar());
  for(; c >= '0' && c <= '9'; x = (x << 3) + (x << 1) + c - '0', c = getchar());
  if(f) x = -x;
}
namespace one {
  const int N = 256;
  int n, m, a[N][N], mp1[N][N], mp2[N][N], idx[N][N];
  int d[N], c[N], has[N], tmp[N];

  inline void init(void) {
    for(int i = 0; i <= n; i ++)
      for(int j = 0; j <= n; j ++)
        mp1[i][j] = mp2[i][j] = idx[i][j] = d[j] = c[j] = has[j] = tmp[j] = 0;
  }
  
  inline void doit(void) {
    queue<int> q; fo(i, n) q.push(i);
    while(!q.empty()) {
      int u = q.front(); q.pop();
      ++ has[u];
      int nxt = mp1[u][has[u]];
      if(!d[nxt] || mp2[nxt][u] < mp2[nxt][d[nxt]]) {
        if(d[nxt]) q.push(d[nxt]);
        c[d[nxt]] = 0;
        d[nxt] = u; c[u] = nxt;
      }
      else if(has[u] != n) q.push(u);
    }
    for(int i = 1; i <= n; i ++)
      cout << c[i] << " ";
    puts("");
  }

  void main(void) {
    read(n); read(m);
    init();
    for(int i = 1; i <= n; i ++) {
      for(int j = 1; j <= m; j ++) {
        int t; read(t);
        if(t) mp1[i][++ mp1[i][0]] = t;
        if(t) idx[i][t] = j;
      }
    }
    fo(i, n) {
      fo(j, n) tmp[j] = j;
      sort(tmp + 1, tmp + n + 1, [&](int a, int b) {
                                   return idx[a][i] > idx[b][i];
                                 });
      fo(j, n) mp2[i][tmp[j]] = j;
    }
    doit();
  }
}
main(void) {
  int T; for(read(T); T --; one::main());
}

猜你喜欢

转载自www.cnblogs.com/foreverpiano/p/9216214.html