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\n",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\n",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\n");
 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("\n");
 98     }
 99     printf("fin\n");
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\n");
138             return;
139         }
140     }
141     printf("TAK\n");
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\n",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 }

转载于:https://www.cnblogs.com/SilverNebula/p/6639758.html

Bzoj3168 [Heoi2013]钙铁锌硒维生素相关推荐

  1. BZOJ3168: [Heoi2013]钙铁锌硒维生素

    传送门 题意 给定一个满秩的矩阵 AAA ,另一个矩阵 BBB 对于 AAA 的每个行向量 AiA_iAi​ 找到一个匹配 BBB 的行向量 BpiB_{p_i}Bpi​​ 使得 AiA_iAi​ 替 ...

  2. BZOJ3168. [HEOI2013]钙铁锌硒维生素(线性代数+二分图匹配)

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=3168 题解 首先,我们需要求出对于任意的 \(i, j(1 \leq i, j \leq ...

  3. bzoj3168 [Heoi2013]钙铁锌硒维生素(矩阵求逆+匈牙利)

    如果把ai替换成bj,这n个向量还是线性无关即可以. 我们求一个C∗A=B,=>C=B∗A−1C∗A=B,=>C=B∗A−1C*A=B,=>C=B*A^{-1} 矩阵求逆可以高斯消元 ...

  4. 【BZOJ3168】[Heoi2013]钙铁锌硒维生素 高斯消元求矩阵的逆+匈牙利算法

    [BZOJ3168][Heoi2013]钙铁锌硒维生素 Description 银河队选手名单出来了!小林,作为特聘的营养师,将负责银河队选手参加宇宙比赛的饮食.众所周知,前往宇宙的某个星球,通常要花 ...

  5. 洛谷 P4100 [HEOI2013]钙铁锌硒维生素 解题报告

    P4100 [HEOI2013]钙铁锌硒维生素 题目描述 银河队选手名单出来了!小林,作为特聘的营养师,将负责银河队选手参加 宇宙比赛的饮食. 众所周知,前往宇宙的某个星球,通常要花费好长好长的时间, ...

  6. BZOJ 3168: [Heoi2013]钙铁锌硒维生素 [线性基 Hungary 矩阵求逆]

    3168: [Heoi2013]钙铁锌硒维生素 题意:给一个线性无关组A,再给一个B,要为A中每个向量在B中选一个可以代替的向量,替换后仍然线性无关.判断可行和求字典序最小的解 PoPoQQQ orz ...

  7. BZOJ 3168 Luogu P4100 [HEOI2013]钙铁锌硒维生素 (矩阵求逆、二分图匹配)

    线性代数+图论好题. 题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=3168 (luogu) https://www.lu ...

  8. [HEOI2013] 钙铁锌硒维生素

    Description 给定2N2N个行向量A1,-,AN,B1,-,BNA_1,\dots,A_N,B_1,\dots,B_N,需要设计一种替换方案,AiA_i被BjB_j替换(i∈[1,N],j∈ ...

  9. 【BZOJ】3168: [Heoi2013]钙铁锌硒维生素

    题解 Ca Fe Zn Se 显然我们既然初始矩阵就能通过线性变换变成单位矩阵,则该矩阵一定有逆 没有逆输出NIE 而且因为这些向量两两正交,则表示一个向量的时候表示方法唯一 那么我们求一个逆可以求出 ...

最新文章

  1. 机器学习 | 图像检索开源项目合集
  2. Docker CE 全自动安装
  3. 关于安装VS2010过程中的错误
  4. linux常用命令-查看文本/cat,tac,more,less,head,tail
  5. 数学——Euler方法求解微分方程详解(python3)
  6. 怎样用命令行生成自己的签名文件keystore
  7. OpenCV imgcodecs写入的实例(附完整代码)
  8. Git笔记(31) 重置揭密
  9. html5 websocket 手机,HTML5 WebSocket 示范
  10. 树莓派入门教程 - 0 - 准备篇 - 0.2 树莓派SSH远程登陆,VNC远程桌面
  11. Android签名机制:生成keystore、签名、查看签名信息
  12. java自学经历分享
  13. find 命令_教你Linux find命令实例教程:15个find命令用法
  14. C++学习足迹---(纯DOS版)五子棋
  15. matlab的基本语法规则_Matlab基本语法与指令
  16. iOS oc对网络图片进行黑白化处理
  17. .md文件简单的转化为pdf文件
  18. 陈丽莎计算机科学与技术专业,关于表彰我校成人高等学历教育2015届毕业生学习奖和优秀学生干部获奖者的通知...
  19. ElasticSearch Cause: Cluster state has not been recovered yet, cannot write to the [null] index
  20. 嘀嘀的费用是优步的两倍?

热门文章

  1. myeclipse 10创建maven项目
  2. C# 写了个获取本机外网IP发送邮件的服务- 分享。
  3. (正)斜杠 与 反斜杠
  4. 常用的Meta标签写法和作用
  5. 5秒钟后自动跳转!!!!
  6. [转]Git远程操作详解
  7. Apache启动报错
  8. 信息安全意识电子期刊第八期
  9. golang内置类型和函数
  10. 进程间通信 —— 命名管道