zoukankan      html  css  js  c++  java
  • Bzoj3168 [Heoi2013]钙铁锌硒维生素

    Time Limit: 20 Sec  Memory Limit: 256 MB
    Submit: 466  Solved: 151

    Description

    银河队选手名单出来了!小林,作为特聘的营养师,将负责银河队选手参加
    宇宙比赛的饮食。众所周知,前往宇宙的某个星球,通常要花费好长好长的时间,人体情况在这之间会发生变化,因此,需要根据每天的情况搭配伙食,来保证营养。小林把人体需要的营养分成了n种,这些营养包括但不限于铁,钙。他准备了2套厨师机器人,一套厨师机器人有n个,每个厨师机器人只会做一道菜,这道菜一斤能提供第i种营养xi微克。想要吃这道菜的时候,只要输入一个数,就能吃到对应数量的这道菜了。为防止摄入过量对身体造成的伤害,每个机器人还有防过量摄入药,只要输入一个数,就能生成一定剂量的药,吃了这些药,就能减少相当于食用对应数目的这道菜提供的营养。
    小林之所以准备2套厨师机器人,正是因为旅途漫漫,难以预计,也许某一个厨师机器人在途中坏掉,要是影响了银河队选手的身体,就不好了。因此,第2套厨师机器人被用来做第1套的备用。小林需要为每一个第1套厨师机器人选一个第2套厨师机器人作备份,使得当这个机器人坏掉时,用备份顶替,整套厨师机器人仍然能搭配出任何营养需求,而且,每个第2套厨师机器人只能当一个第1套厨师机器人的备份。

    Input

    第一行包含一个正整数n。接下来n行,每行n个整数,表示第
    1套厨师机器人做的菜每一斤提供的每种营养。再接下来n行,每行n个整数,表示第2套厨师机器人做的菜每一斤提供的每种营养。

    Output

    第一行是一个字符串,如果无法完成任务,输出“NIE”,否则输
    出“TAK”,并跟着n行,第i行表示第i个第1套机器人的备份是哪一个第2套机器人。为了避免麻烦,如果有多种可能的答案,请给出字典序最小的那一组。

    Sample Input

    3
    100
    010
    001
    230
    078
    009

    Sample Output

    TAK
    1
    23



    HINT

    对于100%的数据,1≤n≤300,所有出现的整数均非负,且不超过10,000。

    Source

    数学问题 矩阵乘法 高斯消元

    图论 二分图匹配

    如果线性无关的向量a1,a2,a3,a4..能线性表出b1,那么前面那个a集合中任意一个向量可以被其他的a向量和b1线性表出(应该是这样)

    设矩阵C*A=B,若C[i][j]!=0,则说明ai和其他某些向量可以表出bj,也就是说用bj可以替换ai

    而$C=B*A_{ }^{-1}$

    求A的逆矩阵,乘以B就得到C

    若bj可以替换ai,则从bj向ai连边。发现C的转置就是连边关系的邻接矩阵。

    然后跑匈牙利算法,若能得到完备匹配,说明有解,否则无解

    然后再用匈牙利算法的模式DFS,贪心地尽量让前面的b匹配前面的a,使字典序最小。

    真是神题

    ↓那个tran()转置其实没必要做,只要建邻接矩阵的时候把i和j翻一下就行

      1 /*by SilverN*/
      2 #include<iostream>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<cstdio>
      6 #define LL long long
      7 using namespace std;
      8 //const int mod=1e9+7;
      9 const int mod=999911657;
     10 const int mxn=303;
     11 int read(){
     12     int x=0,f=1;char ch=getchar();
     13     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     14     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     15     return x*f;
     16 }
     17 int n;
     18 LL ksmul(LL a,LL b){
     19     int res=0;
     20     while(b){
     21         if(b&1)res=((LL)res+a)%mod;
     22         (a<<=1)%=mod;
     23         b>>=1;
     24     }
     25     return res;
     26 }
     27 LL ksm(int a,int k){
     28     LL x=1;
     29     while(k){
     30         if(k&1)x=ksmul(x,a);
     31         a=ksmul(a,a);
     32         k>>=1;
     33     }
     34     return x;
     35 }
     36 struct Mat{
     37     int x[mxn][mxn];
     38     Mat operator * (Mat b){
     39         Mat res;
     40         for(int i=1;i<=n;i++){
     41             for(int j=1;j<=n;j++){
     42                 res.x[i][j]=0;
     43                 for(int k=1;k<=n;k++)
     44                     (res.x[i][j]+=(LL)x[i][k]*b.x[k][j]%mod)%=mod;
     45             }
     46         }
     47         return res;
     48     }
     49     Mat Gauss_inv(){
     50         Mat inv;
     51         int i,j,k;
     52         for(i=1;i<=n;i++)
     53             inv.x[i][i]=1;//初始化单位矩阵 
     54         for(i=1;i<=n;i++){
     55             if(!x[i][i]){
     56                 int p=i;
     57                 for(j=i+1;j<=n;j++){
     58                     if(x[p][i]){p=i;break;}
     59                 }
     60                 for(j=1;j<=n;j++){
     61                     swap(x[p][j],x[i][j]);
     62                     swap(inv.x[p][j],inv.x[i][j]);
     63                 }
     64             }
     65             LL INV=ksm(x[i][i],mod-2);
     66 //          printf("INV:%lld
    ",INV);
     67             for(j=1;j<=n;j++){
     68                 x[i][j]=x[i][j]*INV%mod;
     69                 inv.x[i][j]=inv.x[i][j]*INV%mod;
     70 //              printf("x%d %d:%d
    ",i,j,inv.x[i][j]);
     71             }
     72             for(j=1;j<=n;j++){
     73                 if(j==i)continue;
     74                 LL tmp=(mod-x[j][i])%mod;
     75                 for(k=1;k<=n;k++){
     76                     (x[j][k]+=x[i][k]*tmp%mod)%=mod;
     77                     (inv.x[j][k]+=inv.x[i][k]*tmp%mod)%=mod;
     78                      
     79                 }
     80             }
     81         }
     82         return inv;
     83     }
     84     void tran(){
     85         for(int i=1;i<=n;i++)
     86             for(int j=i+1;j<=n;j++)
     87                 swap(x[i][j],x[j][i]);
     88         return;
     89     }
     90 }a,b,c;
     91 void Debug(Mat a){
     92     printf("Debug
    ");
     93     for(int i=1;i<=n;i++){
     94         for(int j=1;j<=n;j++){
     95             printf("%d ",a.x[i][j]);
     96         }
     97         printf("
    ");
     98     }
     99     printf("fin
    ");
    100     return;
    101 }
    102 //Matrix
    103 int mp[mxn][mxn];
    104 int vis[mxn],Link[mxn];
    105 bool DFS(int u){
    106     for(int i=1;i<=n;i++)
    107         if(mp[u][i] && !vis[i]){
    108             vis[i]=1;
    109             if(!Link[i] || (DFS(Link[i])==1)){
    110                 Link[i]=u;
    111                 return 1;
    112             }
    113         }
    114     return 0;
    115 }
    116 bool Match(int u,int fa){
    117     for(int i=1;i<=n;i++)
    118         if(mp[u][i] && !vis[i]){
    119             vis[i]=1;
    120             if(Link[i]==fa || (Link[i]>fa && Match(Link[i],fa))){
    121                 Link[i]=u;
    122                 return 1;
    123             }
    124         }
    125     return 0;
    126 }
    127 //BP
    128 int ans[mxn];
    129 void Build(){
    130     int i,j;
    131     for(i=1;i<=n;i++)
    132         for(j=1;j<=n;j++)
    133             mp[i][j]=c.x[i][j]?1:0;
    134     for(i=1;i<=n;i++){
    135         memset(vis,0,sizeof vis);
    136         if(!DFS(i)){
    137             printf("NIE
    ");
    138             return;
    139         }
    140     }
    141     printf("TAK
    ");
    142     for(i=1;i<=n;i++){
    143         memset(vis,0,sizeof vis);
    144         Match(i,i);
    145     }
    146     for(i=1;i<=n;i++)ans[Link[i]]=i;
    147     for(i=1;i<=n;i++)printf("%d
    ",ans[i]);
    148     return;
    149 }
    150 //
    151 int main(){
    152     int i,j;
    153     n=read();
    154     for(i=1;i<=n;i++)
    155         for(j=1;j<=n;j++)
    156             a.x[i][j]=read();
    157     for(i=1;i<=n;i++)
    158         for(j=1;j<=n;j++)
    159             b.x[i][j]=read();
    160 //  Debug(a);
    161     a=a.Gauss_inv();
    162     c=b*a;
    163 //  Debug(c);
    164     c.tran();
    165     Build();
    166     return 0;
    167 }
  • 相关阅读:
    google git的使用方法
    C/C++ 开发库 | C/C++ Development Library
    log4cplus c++开源日志系统
    c++配置类
    Markdown基础语法
    Nhibernate 映射关系,一对多 多对一与多对手在映射文件中的体现。
    Nhibernate refers to an unmapped class nhibernate问题的解决(初学者)
    UICollectionView的使用
    Runloop
    UITableView(转)
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6639758.html
Copyright © 2011-2022 走看看