码迷,mamicode.com
首页 > 其他好文 > 详细

【BZOJ】【TJOI2015】线性代数

时间:2015-05-22 22:26:26      阅读:210      评论:0      收藏:0      [点我收藏+]

标签:

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


  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 }
View Code

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]

【BZOJ】【TJOI2015】线性代数

标签:

原文地址:http://www.cnblogs.com/Tunix/p/4523336.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!