zoukankan      html  css  js  c++  java
  • 【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]提出来:$$ egin{aligned} D&=sum_{j=1}^n ig ( sum_{k=1}^n a[k]*b[k][j]-c[j] ig )*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
    ",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]
  • 相关阅读:
    js实现IE6下png背景透明,超简单,超牛!
    SQLSERVER 动态执行SQL sp_executesql与EXEC
    存储过程中的 SET NOCOUNT ON
    sql CHARINDEX
    css让页面居中
    (转)GridView合集
    (转)智能客户端(SmartClient)
    将程序加到启动组
    SQL时间函数详细说明
    独立存储
  • 原文地址:https://www.cnblogs.com/Tunix/p/4523336.html
Copyright © 2011-2022 走看看