zoukankan      html  css  js  c++  java
  • 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<=500

    正解:最大权闭合图。

    翻译一下题意:在$[1,n]$中选出一些数,选出这个数$i$以后第$i$行和第$i$列都会被选到,获得一些贡献,同时产生$c[i]$的代价。问怎样选行列使得贡献最大,求出最大贡献。

    我们注意到,如果第$i$行第$j$列的数选了,那么$c[i]$和$c[j]$也都要选。这相当于是一些贡献依赖于一些代价。那么我们直接建出最大权闭合图,用正权和减去最小割即可。听说代价向贡献连边跑得更快?于是我也这么写了。。

     1 //It is made by wfj_2048~
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <cstring>
     5 #include <cstdlib>
     6 #include <cstdio>
     7 #include <vector>
     8 #include <cmath>
     9 #include <queue>
    10 #include <stack>
    11 #include <map>
    12 #include <set>
    13 #define inf (1<<30)
    14 #define NN (500010)
    15 #define N (510)
    16 #define il inline
    17 #define RG register
    18 #define ll long long
    19 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    20 
    21 using namespace std;
    22 
    23 struct edge{ int nt,to,flow,cap; }g[5000010];
    24 
    25 int head[NN],dis[NN],q[NN],a[N][N],b[N][N],c[N],d[N],n,S,T,sz,ans,num=1;
    26 
    27 il int gi(){
    28     RG int x=0,q=1; RG char ch=getchar();
    29     while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    30     if (ch=='-') q=-1,ch=getchar();
    31     while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
    32     return q*x;
    33 }
    34 
    35 il void insert(RG int from,RG int to,RG int cap){
    36     g[++num]=(edge){head[from],to,0,cap},head[from]=num; return;
    37 }
    38 
    39 il int bfs(RG int S,RG int T){
    40     for (RG int i=1;i<=sz;++i) dis[i]=0;
    41     RG int h=0,t=1; q[t]=S,dis[S]=1;
    42     while (h<t){
    43     RG int x=q[++h],v;
    44     for (RG int i=head[x];i;i=g[i].nt){
    45         v=g[i].to;
    46         if (!dis[v] && g[i].cap>g[i].flow){
    47         q[++t]=v,dis[v]=dis[x]+1;
    48         if (v==T) return 1;
    49         }
    50     }
    51     }
    52     return 0;
    53 }
    54 
    55 il int dfs(RG int x,RG int T,RG int a){
    56     if (x==T || !a) return a; RG int flow=0,f;
    57     for (RG int i=head[x],v;i;i=g[i].nt){
    58     v=g[i].to;
    59     if (dis[v]==dis[x]+1 && g[i].cap>g[i].flow){
    60         f=dfs(v,T,min(a,g[i].cap-g[i].flow));
    61         if (!f){ dis[v]=-1; continue; }
    62         g[i].flow+=f,g[i^1].flow-=f;
    63         flow+=f,a-=f; if (!a) return flow;
    64     }
    65     }
    66     return flow;
    67 }
    68 
    69 il int maxflow(RG int S,RG int T){
    70     RG int flow=0;
    71     while (bfs(S,T)) flow+=dfs(S,T,inf);
    72     return flow;
    73 }
    74 
    75 il void work(){
    76     n=gi(),S=++sz,T=++sz;
    77     for (RG int i=1;i<=n;++i)
    78     for (RG int j=1;j<=n;++j){
    79         a[i][j]=++sz,b[i][j]=gi(),ans+=b[i][j];
    80         insert(a[i][j],T,b[i][j]),insert(T,a[i][j],0);
    81     }
    82     for (RG int i=1;i<=n;++i)
    83     c[i]=gi(),d[i]=++sz,insert(S,d[i],c[i]),insert(d[i],S,0);
    84     for (RG int i=1;i<=n;++i)
    85     for (RG int j=1;j<=n;++j)
    86         if (i!=j){
    87         insert(d[i],a[i][j],inf),insert(a[i][j],d[i],0);
    88         insert(d[j],a[i][j],inf),insert(a[i][j],d[j],0);
    89         } else insert(d[i],a[i][j],inf),insert(a[i][j],d[i],0);
    90     printf("%d
    ",ans-maxflow(S,T)); return;
    91 }
    92 
    93 int main(){
    94     File("linear");
    95     work();
    96     return 0;
    97 }
  • 相关阅读:
    Windows系统环境变量path优先级测试报告
    URI和URL的区别
    智能引导式报错(Class file name must end with .class)
    【Algorithm】冒泡排序
    【C语言】练习2-9
    【C语言】练习2-8
    【C语言】练习2-1
    【C语言】练习1-23
    【C语言】练习1-22
    【C语言】练习1-21
  • 原文地址:https://www.cnblogs.com/wfj2048/p/7117751.html
Copyright © 2011-2022 走看看