题意:
n条鱼,每条鱼有一个价值,然后给出一个交配意愿的图,mp[i][j]表示的是鱼i想和鱼j交配,两条鱼之间只要有一条想交配既可以交配,每条鱼只能和一条鱼交配,所生的孩子的价值是父母价值的异或和,求交配完成后孩子的最大价值和。
思路:
二分图裸题,但是我用的vector存图的板子,T到姥姥家,后来看别人ac代码改成了邻接矩阵93ms就过了,莫名其妙啊
代码:
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>
#include <iostream>
using namespace std;
const int MAXN = 105;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
struct KM {
int n;
int W[MAXN][MAXN];
int Lx[MAXN], Ly[MAXN];
int Left[MAXN];
bool S[MAXN], T[MAXN];
void init (int n) {
this -> n = n;
memset(W, 0, sizeof(W));
}
void AddEdge(int u, int v, int w) {
W[u][v] = w;
}
bool match(int u) {
S[u] = true;
for (int v = 0; v < n; v++) {
if (Lx[u] + Ly[v] == W[u][v] && !T[v]) {
T[v] = true;
if (Left[v] == -1 || match(Left[v])) {
Left[v] = u;
return true;
}
}
}
return false;
}
void update() {
int a = INF;
for (int u = 0; u < n; u++) if (S[u]) {
for (int v = 0; v < n; v++) {
if (!T[v]) a = min(a, Lx[u] + Ly[v] - W[u][v]);
}
}
for (int i = 0; i < n; i++) {
if (S[i]) Lx[i] -= a;
if (T[i]) Ly[i] += a;
}
}
void solve() {
for (int i = 0; i < n; i++) {
Lx[i] = *max_element(W[i], W[i] + n);
Left[i] = -1;
Ly[i] = 0;
}
for (int u = 0; u < n; u++) {
while (true) {
for (int i = 0; i < n; i++) S[i] = T[i] = false;
if (match(u)) break;
else update();
}
}
}
} km;
int a[MAXN];
char mp[MAXN][MAXN];
int main() {
int n;
while (scanf("%d", &n), n) {
km.init(n);
for (int i = 0; i < n; i++)
scanf("%d", &a[i]);
for (int i = 0; i < n; i++) {
scanf("%s", mp[i]);
for (int j = 0; j < n; j++) {
if (mp[i][j] == '1') {
km.AddEdge(i, j, a[i] ^ a[j]);
}
}
}
km.solve();
int ans = 0;
for (int i = 0; i < n; i++) {
if (km.Left[i] == -1) continue;
ans += km.W[km.Left[i]][i];
}
printf("%d\n", ans);
}
return 0;
}