【BZOJ】【TJOI2015】线性代数

网络流/最小割/最大权闭合图



  2333好开心,除了一开始把$500^2$算成25000……导致数组没开够RE了一发,可以算是一次AC~

  咳咳还是回归正题来说题解吧:

  一拿到这道题,我就想:这是什么鬼玩意……矩阵乘法早忘了……画了半天也想不起来到底是谁乘谁,只记得有个式子:$c[i][j]=\sum a[i][k]*b[k][j]$

  好吧没关系,既然画图不行了,我们就先拿这个东西,纯代数来搞!

  D的表达式,里面那层我们可以写成:$\sum a[i][k]*b[k][j] - c[i][j]$

  然而a和c都是1*N的矩阵,简化一下,我们得到:$$ \sum a[k]*b[k][j]-c[j]$$

  所以我们把D的表达式转化一下,发现可以把c[j]提出来:$$ \begin{aligned} D&=\sum_{j=1}^n \big ( \sum_{k=1}^n a[k]*b[k][j]-c[j] \big )*a[j] \\ &=\sum_{j=1}^n \sum_{k=1}^n a[j]*a[k]*b[k][j]-\sum_{k=1}^n a[j]*c[j] \end{aligned} $$

  这时我们发现:b[j][k]和c[j]前面分别乘了一或两个0/1变量……感觉像什么……最大权闭合图对不对……同时选了 j 和 k 的话可以得到b[j][k]的收益,但是选 j 得付出c[j]的代价!

  这时候我们就可以轻松+愉快的进行建图……

好久没写过网络流了,一次写对Dinic还是蛮感动的

  1 /**************************************************************
  2     Problem: 3996
  3     User: Tunix
  4     Language: C++
  5     Result: Accepted
  6     Time:584 ms
  7     Memory:29152 kb
  8 ****************************************************************/
  9
 10 //BZOJ 3996
 11 #include<queue>
 12 #include<cstdio>
 13 #include<cstring>
 14 #include<cstdlib>
 15 #include<iostream>
 16 #include<algorithm>
 17 #define rep(i,n) for(int i=0;i<n;++i)
 18 #define F(i,j,n) for(int i=j;i<=n;++i)
 19 #define D(i,j,n) for(int i=j;i>=n;--i)
 20 #define pb push_back
 21 using namespace std;
 22 typedef long long LL;
 23 inline int getint(){
 24     int r=1,v=0; char ch=getchar();
 25     for(;!isdigit(ch);ch=getchar()) if (ch==‘-‘) r=-1;
 26     for(; isdigit(ch);ch=getchar()) v=v*10-‘0‘+ch;
 27     return r*v;
 28 }
 29 const int N=300010,M=1000010,INF=1e9;
 30 /*******************template********************/
 31 int n,ans;
 32 struct edge{int to,v;};
 33 struct Net{
 34     edge E[M<<1];
 35     int head[N],next[M<<1],cnt;
 36     void ins(int x,int y,int z){
 37         E[++cnt]=(edge){y,z}; next[cnt]=head[x]; head[x]=cnt;
 38     }
 39     void add(int x,int y,int z){ins(x,y,z); ins(y,x,0);}
 40     int d[N],S,T,cur[N];
 41     queue<int>Q;
 42     bool mklevel(){
 43         memset(d,-1,sizeof d);
 44         d[S]=0;
 45         Q.push(S);
 46         while(!Q.empty()){
 47             int x=Q.front(); Q.pop();
 48             for(int i=head[x];i;i=next[i])
 49                 if (d[E[i].to]==-1 && E[i].v){
 50                     d[E[i].to]=d[x]+1;
 51                     Q.push(E[i].to);
 52                 }
 53         }
 54         return d[T]!=-1;
 55     }
 56     int dfs(int x,int a){
 57         if (x==T) return a;
 58         int flow=0;
 59         for(int &i=cur[x];i && flow<a;i=next[i])
 60             if (d[E[i].to]==d[x]+1 && E[i].v){
 61                 int f=dfs(E[i].to,min(E[i].v,a-flow));
 62                 E[i].v-=f;
 63                 E[i^1].v+=f;
 64                 flow+=f;
 65             }
 66         if (!flow) d[x]=-1;
 67         return flow;
 68     }
 69     void Dinic(){
 70         while(mklevel()){
 71             F(i,S,T) cur[i]=head[i];
 72             ans-=dfs(S,INF);
 73         }
 74     }
 75     void init(){
 76         cnt=1; ans=0;
 77         n=getint(); S=0; T=n*(n+1)+1;
 78         int x;
 79         F(i,1,n) F(j,1,n){
 80             x=getint();
 81             add(i*n+j,T,x);
 82             add(i,i*n+j,INF);
 83             add(j,i*n+j,INF);
 84             ans+=x;
 85         }
 86         F(i,1,n){
 87             x=getint();
 88             add(S,i,x);
 89         }
 90         Dinic();
 91         printf("%d\n",ans);
 92     }
 93 }G1;
 94 int main(){
 95 #ifndef ONLINE_JUDGE
 96     freopen("3996.in","r",stdin);
 97     freopen("3996.out","w",stdout);
 98 #endif
 99     G1.init();
100     return 0;
101 }

3996: [TJOI2015]线性代数

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 590  Solved: 414
[Submit][Status][Discuss]

Description

给出一个N*N的矩阵B和一个1*N的矩阵C。求出一个1*N的01矩阵A.使得

D=(A*B-C)*A^T最大。其中A^T为A的转置。输出D

Input

第一行输入一个整数N,接下来N行输入B矩阵,第i行第J个数字代表Bij.

接下来一行输入N个整数,代表矩阵C。矩阵B和矩阵C中每个数字都是不超过1000的非负整数。

Output

输出最大的D

Sample Input

3
1 2 1
3 1 0
1 2 3
2 3 7

Sample Output

2

HINT

1<=N<=500

Source

[Submit][Status][Discuss]

时间: 2024-10-19 23:45:58

【BZOJ】【TJOI2015】线性代数的相关文章

BZOJ 3966 TJOI2015 线性代数 网络流

题目大意:给定一个n?n的矩阵B和一个1?n的行向量C,求一个1?n的01矩阵A,使(A×B?C)×AT最大 (A×B?C)×AT=A×B×AT?C×AT 我们可以考虑有n个物品,每个物品选不选对应A中每个位置是1还是0 那么行向量C可以看做每个物品的代价 而矩阵B可以看做同时选择某两个物品时的收益 那么这个模型就被我们直接分析出来了,网络流走起~ #include <cstdio> #include <cstring> #include <iostream> #inc

[TJOI2015]线性代数

题目链接 戳我 \(Describe\) 题目描述 为了提高智商,\(ZJY\)开始学习线性代数.她的小伙伴菠萝给她出了这样一个问题:给定一个\(n×n\)的矩阵\(B\)和一个\(1×n\)的矩阵\(C\).求出一个\(1×n\)的\(01\)矩阵\(A\).使得\(D=(A*B-C)*A^T\) 最大,其中\(A^T\)为\(A\)的转置.输出\(D\). 输入格式: 第一行输入一个整数\(n\).接下来\(n\)行输入\(B\)矩阵,第\(i\)行第\(j\)个数代表\(B\)接下来一行输

BZOJ3996[TJOI2015]线性代数

Description 给出一个N*N的矩阵B和一个1*N的矩阵C.求出一个1*N的01矩阵A.使得 D=(A*B-C)*A^T最大.其中A^T为A的转置.输出D Input 第一行输入一个整数N,接下来N行输入B矩阵,第i行第J个数字代表Bij. 接下来一行输入N个整数,代表矩阵C.矩阵B和矩阵C中每个数字都是不超过1000的非负整数. Output 输出最大的D Sample Input 3 1 2 1 3 1 0 1 2 3 2 3 7 Sample Output 2 HINT 1<=N<

【bzoj3996】[TJOI2015]线性代数 最大权闭合图

题目描述 给出一个N*N的矩阵B和一个1*N的矩阵C.求出一个1*N的01矩阵A.使得 D=(A*B-C)*A^T最大.其中A^T为A的转置.输出D 输入 第一行输入一个整数N,接下来N行输入B矩阵,第i行第J个数字代表Bij. 接下来一行输入N个整数,代表矩阵C.矩阵B和矩阵C中每个数字都是不超过1000的非负整数. 输出 输出最大的D 样例输入 3 1 2 1 3 1 0 1 2 3 2 3 7 样例输出 2 题解 网络流最大权闭合图 (推导过程什么的不重要,只要注意一下矩阵乘法不满足结合律

bzoj1497: [NOI2006]最大获利&amp;&amp;3996: [TJOI2015]线性代数

给出一个N*N的矩阵B和一个1*N的矩阵C.求出一个1*N的01矩阵A.使得 D=(A*B-C)*A^T最大.其中A^T为A的转置.输出D Input 第一行输入一个整数N,接下来N行输入B矩阵,第i行第J个数字代表Bij. 接下来一行输入N个整数,代表矩阵C.矩阵B和矩阵C中每个数字都是不超过1000的非负整数. Output 输出最大的D Sample Input 3 1 2 1 3 1 0 1 2 3 2 3 7 Sample Output 2 化简一下式子, 给出一个N*N的矩阵B和一个

BZOJ3996 TJOI2015线性代数

先把矩阵式子化简 原式=∑i=1n∑j=1nA[i]∗B[i][j]∗A[j]−∑i=1nA[i]∗C[i] 因此我们发现问题转化为选取一个点所获收益是B[i][j],代价是C[i][j] 这是一个最小割问题. 先把答案记做所有b的和. 将边按照s——>p[i][j](b[i][j])  p[i][j]——>i p[i][j]——>j i——>t(c[i])这样建图后我们删去的那个最小割意义就是花费最少的使得整个图不连通的量 如果删在左边就意味着这件物品我们不要了,如果删去右边的话

BZOJ_3996_[TJOI2015]线性代数_最大权闭合子图

Description 给出一个N*N的矩阵B和一个1*N的矩阵C.求出一个1*N的01矩阵A.使得 D=(A*B-C)*A^T最大.其中A^T为A的转置.输出D Input 第一行输入一个整数N,接下来N行输入B矩阵,第i行第J个数字代表Bij. 接下来一行输入N个整数,代表矩阵C.矩阵B和矩阵C中每个数字都是不超过1000的非负整数. Output 输出最大的D Sample Input 3 1 2 1 3 1 0 1 2 3 2 3 7 Sample Output 2 HINT 1<=N<

bzoj 3996 线性代数 —— 最大权闭合子图

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3996 把题中的式子拆开看看,发现就是如下关系: 如果 a[i] == 1 && a[j] == 1,则 b[i][j] 有贡献: 如果 a[i] == 1,则 -c[i] 有贡献: 所以就是最大权闭合子图的模型,b[i][j] 向 a[i] 和 a[j] 连边,a[i] 向 c[i] 连边: 而 c[i] 这个点实际上没什么用,直接变成 a[i] 向 T 连边,边权是 c[i] 即可

[BZOJ 3996] [TJOI 2015] 线性代数

3996: [TJOI2015]线性代数 Time Limit: 10 SecMemory Limit: 128 MB Description 给出一个N*N的矩阵B和一个1*N的矩阵C.求出一个1*N的01矩阵A.使得 D=(A*B-C)*A^T最大.其中A^T为A的转置.输出D Input 第一行输入一个整数N,接下来N行输入B矩阵,第i行第J个数字代表Bij. 接下来一行输入N个整数,代表矩阵C.矩阵B和矩阵C中每个数字都是不超过1000的非负整数. Output 输出最大的D Sampl