[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\)接下来一行输入\(n\)个整数,代表矩阵\(C\)。矩阵\(B\)和矩阵\(C\)中每个数字都是不过\(1000\)的非负整数

输出格式:

输出一个整数,表示最大的\(D\)。

输入样例:
3
1 2 1
3 1 0
1 2 3
2 3 7

输出样例:
2

\(Solution\)

首先来化简一下式子

\[D=(A*B-C)*A^T\]
\[=\sum_{i=1}^{n}(\sum_{j=1}^{n}A_j*B_{j,i}-C_i)*A_i\]
\[=\sum_{i=1}^{n}\sum_{j=1}^{n}A_i*A_j*B_{i,j}-\sum_{i=1}^{n}C_i*A_i\]

因为题目已经说明了\(A\)是一个\(01\)串,所以我们可以发现当\(A_i\)为\(0\)的时候对答案并没有任何贡献,不用计算。当\(A_i\)为\(1\)时,会有\(C_i\)的花费。但如果同时选\(j\)会有\(B_{i,j}\)的花费.所以这显然是一个最小割模型了。讲1看为选,0为不选

建图:

  • 将每个\(B_{ij}\)看做一个点,总共有\(n*n\)个点。将这\(S\)和这\(n*n\)个点相连,流量为\(B_{i,j}\)
  • 新建\(n\)个点。将这些点和\(T\)相连,流量为\(C_i\)
  • 将\(n*n\)个点和新建节点中的\(i,j\)相连,流量为\(inf\)

答案就是\(B\)矩阵内的和-最小割

\(Code\)

#include<bits/stdc++.h>
#define inf 1e9
using namespace std;
typedef long long ll;
int read(){
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    return x*f;
}
struct node{
    int to,next,v;
}a[2000001];
int head[1000001],cnt,n,m,s,t,x,y,z,dep[260000],sum,cur[260000];
void add(int x,int y,int c){
    a[++cnt].to=y,a[cnt].next=head[x],a[cnt].v=c,head[x]=cnt;
    a[++cnt].to=x,a[cnt].next=head[y],a[cnt].v=0,head[y]=cnt;
}
queue<int> q;
int bfs(){
    memset(dep,0,sizeof(dep));
    q.push(s);
    dep[s]=1;
    while(!q.empty()){
        int now=q.front();
        q.pop();
        for(int i=head[now];i;i=a[i].next){
            int v=a[i].to;
            if(!dep[v]&&a[i].v>0)
                dep[v]=dep[now]+1,q.push(v);
        }
    }
    if(dep[t])
        return 1;
    return 0;
}
int dfs(int k,int list){
    if(k==t||!list)
        return list;
    for(int &i=cur[k];i;i=a[i].next){
        int v=a[i].to;
        if(dep[v]==dep[k]+1&&a[i].v>0){
            int p=dfs(v,min(list,a[i].v));
            if(p){
                a[i].v-=p;
                i&1?a[i+1].v+=p:a[i-1].v+=p;
                return p;
            }
        }
    }
    return 0;
}
int Dinic(){
    int ans=0,k;
    while(bfs()){
        for(int i=s;i<=t;i++)
            cur[i]=head[i];
        while((k=dfs(s,inf)))
            ans+=k;
    }
    return ans;
}
int main(){
    n=read(),s=0,t=n*n+n+1;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            x=read(),sum+=x,add(s,(i-1)*n+j,x),add((i-1)*n+j,i+n*n,inf),add((i-1)*n+j,j+n*n,inf);
    for(int i=1;i<=n;i++)
        x=read(),add(i+n*n,t,x);
    printf("%d\n",sum-Dinic());
}

原文地址:https://www.cnblogs.com/hbxblog/p/10280551.html

时间: 2024-10-14 11:34:42

[TJOI2015]线性代数的相关文章

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和一个

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

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】【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]$ 然而

[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

网络流复习计划

既然是复习网络流,那就不会去做水题了吧233 A.BZOJ3996 TJOI2015线性代数 看到题就被吓坏了2333.线性代数根本没看完好吗? 然后... MD转个模型就是网络流了 “题目大意:给定一个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可以看做同时选择某两个物品时的收益 那么这个模型