luogu P4100 [HEOI2013]钙铁锌硒维生素

https://www.luogu.com.cn/problem/P4100
题目大意:
在这里插入图片描述
首先构造两个矩阵A,B
把A,B转置一下变成 A T , B T A^T,B^T AT,BT
就相当于是写成把若干个向量拼成矩阵的形式
然后可以得到
B = R A B=RA B=RA保证 R [ i ] [ j ] ! = 0 R[i][j]!=0 R[i][j]!=0才能让 A [ i ] A[i] A[i] B [ j ] B[j] B[j]代替,不然说明 B [ j ] B[j] B[j]会与除了 A [ i ] A[i] A[i]外的向量线性相关
所以 R = B A − 1 \large R=BA^{-1} R=BA1
具体做的话可以在 A A A后面接一个伴随矩阵 B B B然后把 A A A消元成单位矩阵,这时候 B B B就变成 R R R
再根据 R R R连边跑最大匹配(字典序最小的)即可
code:

#include<bits/stdc++.h>
#define N 605
using namespace std;
const double eps = 1e-9;
int vis[N], match[N], n;
double a[N][N], b[N][N];
int dfs(int u) {
    for(int v = 1; v <= n; v ++) if(!vis[v] && fabs(b[u][v]) > eps) {
        vis[v] = 1;
        if(!match[v] || dfs(match[v])) {
            match[v] = u;
            return 1;
        }
    }
    return 0;
}
int dfss(int u, int fr) {
    for(int v = 1; v <= n; v ++) if(!vis[v] && fabs(b[u][v]) > eps) {
        vis[v] = 1;
        if(match[v] == fr || (match[v] > fr && dfss(match[v], fr))) {
            match[v] = u;
            return v;
        }
    }
    return 0;
}
int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= n; j ++)
            scanf("%lf", &a[j][i]);
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= n; j ++)
            scanf("%lf", &b[j][i]);
    for(int i = 1; i <= n; i ++) {
        int j = i;
        for(int k = i + 1; k <= n; k ++) if(fabs(a[k][i]) > fabs(a[j][i])) j = k;
        if(j != i) swap(a[i], a[j]), swap(b[i], b[j]);
        double x = a[i][i];
        if(fabs(x) < eps) { printf("NIE"); return 0;}
        for(int j = 1; j <= n; j ++) a[i][j] /= x, b[i][j] /= x;
        for(int j = 1; j <= n; j ++) if(j != i) {
            double t = a[j][i];
            for(int k = 1; k <= n; k ++) {
                a[j][k] -= a[i][k] * t;
                b[j][k] -= b[i][k] * t;
            }
        }
    }
//    for(int i = 1; i <= n; i ++) {
//        for(int j = 1; j <= n; j ++) printf("%.3lf ", b[i][j]); printf("\n");
//    }
    for(int i = 1; i <= n; i ++) {
        memset(vis, 0, sizeof vis);
        if(!dfs(i)) { printf("NIE"); return 0;}
    }
  //  for(int i = 1; i <= n; i ++) printf(" %d ", match[i]); printf("\n");
    puts("TAK");
    for(int i = 1; i <= n; i ++) {
        memset(vis, 0, sizeof vis);
        printf("%d\n", dfss(i, i));
    }
    return 0;
}

posted @ 2021-07-16 15:58  lahlah  阅读(43)  评论(0编辑  收藏  举报