• bzoj3168 钙铁锌硒维生素 (矩阵求逆+二分图最小字典序匹配)


    设第一套为A,第二套为B

    先对于每个B[i]判断他能否替代A[j],即B[i]与其他的A线性无关

    设$B[i]=sumlimits_{k}{c[k]*A[k]}$,那么只要看c[j]是否等于零即可,如果c[j]=0,就意味着可以用A[j]以外的线性表达出B[i],所以不能B[i]替换A[j],否则可以

    于是高斯消元求出c矩阵,问题就转化成了求二分图的最小字典序匹配

    先跑一遍匈牙利判下是否无解,然后以它为基准解再贪心地求一遍答案

    具体地说,你做到第i个的时候,前i-1都要固定住,其他的和普通匈牙利是一样的

      1 #include<bits/stdc++.h>
      2 #include<tr1/unordered_map>
      3 #define CLR(a,x) memset(a,x,sizeof(a))
      4 #define MP make_pair
      5 using namespace std;
      6 typedef long long ll;
      7 typedef unsigned long long ull;
      8 typedef pair<int,int> pa;
      9 typedef long double ld;
     10 const int maxn=303,P=998244353;
     11 
     12 inline ll rd(){
     13     ll x=0;char c=getchar();int neg=1;
     14     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
     15     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
     16     return x*neg;
     17 }
     18 
     19 int N;
     20 int a[maxn][maxn*2],b[maxn][maxn],c[maxn][maxn];
     21 bool can[maxn][maxn];
     22 
     23 inline int fpow(int x,int y){
     24     int re=1;
     25     while(y){
     26         if(y&1) re=1ll*x*re%P;
     27         x=1ll*x*x%P,y>>=1;
     28     }return re;
     29 }
     30 
     31 inline void getinv(){
     32     for(int i=1;i<=N;i++){
     33         a[i][i+N]=1;
     34     }
     35     for(int i=1;i<=N;i++){
     36         int mi=i;
     37         for(int j=i+1;j<=N;j++) if(a[j][i]) mi=j;
     38         swap(a[mi],a[i]);
     39         int iv=fpow(a[i][i],P-2);
     40         for(int j=N*2;j>=i;j--) a[i][j]=1ll*a[i][j]*iv%P;
     41         for(int j=i+1;j<=N;j++){
     42             for(int k=N*2;k>=i;k--) a[j][k]=(a[j][k]-1ll*a[i][k]*a[j][i])%P;
     43         }
     44     }
     45     for(int i=N;i;i--){
     46         for(int j=i-1;j;j--){
     47             for(int k=N+1;k<=N*2;k++) a[j][k]=(a[j][k]-1ll*a[j][i]*a[i][k])%P;
     48         }
     49     }
     50     for(int i=1;i<=N;i++){
     51         for(int j=1;j<=N;j++) a[i][j]=a[i][j+N];
     52     }
     53 }
     54 
     55 int bel[maxn],to[maxn];bool flag[maxn];
     56 
     57 bool dfs(int x){
     58     for(int i=1;i<=N;i++){
     59         if(!can[x][i]||flag[i]) continue;
     60         flag[i]=1;
     61         if(!bel[i]||dfs(bel[i])){bel[i]=x,to[x]=i;return 1;}
     62     }return 0;
     63 }
     64 bool dfs2(int x,int y){
     65     for(int i=1;i<=N;i++){
     66         if(!can[x][i]||flag[i]) continue;
     67         flag[i]=1;
     68         if(bel[i]==y||(bel[i]>y&&dfs2(bel[i],y))){to[x]=i,bel[i]=x;return 1;}
     69     }return 0;
     70 }
     71 
     72 int main(){
     73     //freopen("","r",stdin);
     74     N=rd();
     75     for(int i=1;i<=N;i++){
     76         for(int j=1;j<=N;j++) a[i][j]=rd();
     77     }
     78     for(int i=1;i<=N;i++){
     79         for(int j=1;j<=N;j++) b[i][j]=rd();
     80     }
     81     getinv();
     82     for(int i=1;i<=N;i++){
     83         for(int j=1;j<=N;j++){
     84             for(int k=1;k<=N;k++){
     85                 c[i][j]=(c[i][j]+1ll*b[i][k]*a[k][j])%P;
     86             }
     87         }
     88     }
     89     for(int i=1;i<=N;i++){
     90         for(int j=1;j<=N;j++){
     91             if(c[i][j]) can[j][i]=1;
     92         }
     93     }/*
     94     for(int i=rd();i;i--){
     95         int a=rd(),b=rd();
     96         can[a][b]=1;
     97     }*/
     98     bool bl=1;
     99     for(int i=1;i<=N;i++){
    100         CLR(flag,0);
    101         if(!dfs(i)){bl=0;break;}
    102     }
    103     if(!bl) printf("NIE
    ");
    104     else{
    105         printf("TAK
    ");
    106         for(int i=1;i<=N;i++){
    107             CLR(flag,0);
    108             dfs2(i,i);
    109         }
    110         for(int i=1;i<=N;i++){
    111             printf("%d
    ",to[i]);
    112         }
    113     }
    114     return 0;
    115 }
  • 相关阅读:
    java日常问题和技巧1(BigDecimal与int相互转换、判断某元素是否在数组中、求两个List并集、int[]转Integer[])
    窗口小部件基础编写V1.0----没有Service
    使用MyBatis遇到的问题及解决方法(一)(持续更新)
    java工具类集合(一)
    idea部分操作(一)----持续更新
    单向链表(篇九)
    结构体(篇八)
    指针与字符串(篇七)
    数组字符串(篇六)
    循环与函数(篇五)
  • 原文地址:https://www.cnblogs.com/Ressed/p/10476419.html
Copyright © 2020-2023  润新知