简单题意
有一堆鱼,如果鱼认为其他鱼是雌鱼,则会‘攻击’,‘攻击’以后鱼产两鱼价值异或值数量的卵,一条鱼只能攻击一次,求最大的产卵量
思路
如果有攻击欲望则连边,边权值为两鱼的异或值,然后跑KM算法求得最大权即可,模板题。
代码
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = 105;
const int inf = 1e9;
int mat[maxn][maxn];
int sx[maxn], sy[maxn], lx[maxn], ly[maxn];
int match[maxn],dis[maxn];
int n;
int Find(int x)
{
sx[x] = 1;
for(int i = 0; i < n; i++){
if(sy[i] == 1) {
continue;
}
int temp = lx[x] + ly[i] - mat[x][i];
if(temp == 0){
sy[i] = 1;
if(match[i] == -1 || Find(match[i]) == 1){
match[i] = x;
return 1;
}
}
else {
dis[i] = dis[i] > temp ? temp : dis[i];
}
}
return 0;
}
int KM(){
memset(match, -1, sizeof(match));
memset(ly, 0, sizeof(ly));
for(int i = 0; i < n; i++){
lx[i] = mat[i][0];
for(int j = 1; j < n; j++)
if(lx[i] < mat[i][j])
lx[i] = mat[i][j];
}
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++)
dis[j] = inf;
while(1){
memset(sx, 0, sizeof(sx));
memset(sy, 0, sizeof(sy));
if(Find(i) == 1) {
break;
}
int mi = inf;
for(int k = 0; k < n; k++)
if(sy[k] == 0 && mi > dis[k]) mi = dis[k];
for(int j = 0; j < n; j++){
if(sx[j] == 1) lx[j] -= mi;
if(sy[j] == 1) ly[j] += mi;
}
}
}
int ret = 0;
for(int i = 0; i < n; i++) {
ret += mat[match[i]][i];
}
return ret;
}
int va[maxn] ;
int main() {
int T;
while(~scanf("%d", &T) && T) {
n = T;
for(int i = 0 ; i < T ; i ++) {
scanf("%d", &va[i]);
}
memset(mat, 0, sizeof mat);
char str[maxn];
for(int i = 0 ; i < T ; i ++) {
scanf("%s", str);
for(int k = 0 ; k < T ; k ++) {
if(str[k] == '1') {
mat[i][k] = va[i] ^ va[k];
}
}
}
int ans = KM();
printf("%d\n", ans);
}
}