3996: [TJOI2015]线性代数

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1054  Solved: 684
[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

Solution

首先来化简一下题目中的式子:

设$E=A*B$,很显然E为一个1×N的矩阵,那么有$E_{1,j}=\sum_{i=1}^{N}A_{1,i}B_{i,j}$

那么$A*B-C$就可以化成$F_{1,j}=\sum_{i=1}^{N}A_{1,i}B_{i,j}-C_{1,j}$

那么进一步化简$D_{1,1}=\sum_{j=1}^{N}\left ( \left ( \sum_{i=1}^{N}A_{1,i}B_{i,j}-C_{1,j} \right )*A'_{j,1} \right )$

最后化成:$D=\sum_{i=1}^{N}\sum_{j=1}^{N}A_{i}A_{j}B_{i,j}-\sum_{i=1}^{N}A_{i}C_{i}$

那么从式子的角度去思考建图由于$A$是一个0/1矩阵,不妨把$A$看做“选”或“不选”,那么$B_{i,j}$看做同时选$i$和$j$两个物品的收益,$C_{i}$可以看做选第$i$个物品的代价。

也就是说选$B_{i,j}$必须选$C_{i},C_{j}$

最大权闭合子图.....

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-')f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define maxn 300010
#define maxm 3000010
int N,tot,ans;
struct Edgenode{int to,next,cap;}edge[maxm];
int head[maxn],cnt=;
void add(int u,int v,int w)
{cnt++;edge[cnt].to=v;edge[cnt].cap=w;edge[cnt].next=head[u];head[u]=cnt;}
void insert(int u,int v,int w)
{add(u,v,w);add(v,u,);}
//
#define inf 0x7fffffff
int dis[maxn],q[maxn<<],cur[maxn],S,T;
bool bfs()
{
for (int i=S; i<=T; i++) dis[i]=-;
q[]=S; int he=,ta=;
while (he<ta)
{
int now=q[he++];
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].cap && dis[edge[i].to]==-)
dis[edge[i].to]=dis[now]+,q[ta++]=edge[i].to;
}
return dis[T]!=-;
}
int dfs(int loc,int low)
{
if (loc==T) return low;
int w,used=;
for (int i=cur[loc]; i; i=edge[i].next)
if (edge[i].cap && dis[edge[i].to]==dis[loc]+)
{
w=dfs(edge[i].to,min(low-used,edge[i].cap));
edge[i].cap-=w; edge[i^].cap+=w;
used+=w; if (edge[i].cap) cur[loc]=i;
if (used==low) return low;
}
if (!used) dis[loc]=-;
return used;
}
int dinic()
{
int tmp=;
while (bfs())
{
for (int i=S; i<=T; i++) cur[i]=head[i];
tmp+=dfs(S,inf);
}
return tmp;
}
//
int main()
{
N=read(); S=,T=N+N*N+;
for (int i=; i<=N; i++)
for (int x,j=; j<=N; j++)
x=read(),tot+=x,insert((i-)*N+j+N,T,x),
insert(i,(i-)*N+j+N,inf),insert(j,(i-)*N+j+N,inf);
for (int x,i=; i<=N; i++)
x=read(),insert(S,i,x);
ans=dinic();
printf("%d\n",tot-ans);
return ;
}

正解被喝水路过的ShallWe直接秒....不然我还没往最小割模型上靠...

最新文章

  1. 【BZOJ】3495: PA2010 Riddle
  2. SQL ORDER BY 子句
  3. 性能检测工具介绍-Linux系统命令行
  4. opencv笔记3:trackbar简单使用
  5. Struts2 + Spring + Hibernate 通用 Service 和 DAO
  6. http方式的联调经验
  7. 字符串匹配算法之Sunday算法
  8. zf-启动项目报错Server 127.0.0.1 has no instance named dlx 解决办法
  9. ORACLE 程序包
  10. ThreadLocal使用和原理简析
  11. 【转】mysql热备
  12. [原]Jenkins(十九) jenkins再出发之jenkins邮件通知
  13. 微软BI SSIS 2012 ETL 控件与案例精讲面试 200 问(SSIS 面试题,ETL 面试题)
  14. oracle sqlplus常用命令大全
  15. C++中基类虚析构函数的作用及其原理分析
  16. python2 中 unicode 和 str 之间的转换及与python3 str 的区别
  17. background-position为什么会出现负值?
  18. 将Python文件打包为exe文件,并在控制台运行之简易教程
  19. 基于html5和jquery的篮球跳动游戏
  20. [golang note] 错误处理

热门文章

  1. iOS - 用 UIBezierPath 实现果冻效果
  2. log4j.properties 详解与配置步骤(转)
  3. Android手机浏览器访问本地网络相关问题
  4. PHP中$_SERVER的详细参数与说明
  5. Lowest Common Ancestor of a Binary Tree
  6. mysql 控制台上传数据库
  7. [转]关于Python中的yield
  8. 理解CDN
  9. Android下常见动画
  10. canvas边界与摩擦力