【BZOJ 3996】 3996: [TJOI2015]线性代数 (最小割)

3996: [TJOI2015]线性代数

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1368  Solved: 832

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

 

 

【分析】

  化一下式子得到$D=\sum_{i=1}^{n}\sum_{j=1}^{n}A_i * A_j * B_{ij} - \sum_{i=1}^{n} A_i * C_i$

  网络流建图。

  S→Dot(i,j),流量为bij

  Dot(i,j)→i 以及 Dot(i,j)→j,流量为 ∞

  连边 i→T,流量为ci

  设最小割为$x$,那么答案就是

                  
                $\sum_{i=1}^{n}\sum_{j=1}^{n} B_{ij} - x$

   经典模型??不能弄成类似二分图那样的模型就只能这样了,虽然点很多,但是图比较简单应该还是很快吧?

 

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<queue>
  7 using namespace std;
  8 #define Maxn 510
  9 #define INF 0xfffffff
 10 
 11 int mymin(int x,int y) {return x<y?x:y;}
 12 
 13 struct node
 14 {
 15     int x,y,f,next,o;
 16 }t[Maxn*Maxn*20];
 17 int first[Maxn*Maxn*10],len;
 18 
 19 void ins(int x,int y,int f)
 20 {
 21     t[++len].x=x;t[len].y=y;t[len].f=f;
 22     t[len].next=first[x];first[x]=len;t[len].o=len+1;
 23     t[++len].x=y;t[len].y=x;t[len].f=0;
 24     t[len].next=first[y];first[y]=len;t[len].o=len-1;
 25 }
 26 
 27 int ans;
 28 int dis[Maxn*Maxn*10],st,ed;
 29 queue<int > q;
 30 bool bfs()
 31 {
 32     memset(dis,-1,sizeof(dis));
 33     while(!q.empty()) q.pop();
 34     dis[st]=0;q.push(st);
 35     while(!q.empty())
 36     {
 37         int x=q.front();
 38         for(int i=first[x];i;i=t[i].next) if(t[i].f>0)
 39         {
 40             int y=t[i].y;
 41             if(dis[y]==-1)
 42             {
 43                 dis[y]=dis[x]+1;
 44                 q.push(y);
 45             }
 46         }
 47         q.pop();
 48     }
 49     if(dis[ed]==-1) return 0;
 50     return 1;
 51 }
 52 
 53 int ffind(int x,int flow)
 54 {
 55     if(x==ed) return flow;
 56     int now=0;
 57     for(int i=first[x];i;i=t[i].next) if(t[i].f>0)
 58     {
 59         int y=t[i].y;
 60         if(dis[y]==dis[x]+1)
 61         {
 62             int a=ffind(y,mymin(flow-now,t[i].f));
 63             t[i].f-=a;
 64             t[t[i].o].f+=a;
 65             now+=a;
 66         }
 67         if(now==flow) break;
 68     }
 69     if(now==0) dis[x]=0;
 70     return now;
 71 }
 72 
 73 void max_flow()
 74 {
 75     while(bfs())
 76     {
 77         ans-=ffind(st,INF);
 78     }
 79 }
 80 
 81 int main()
 82 {
 83     freopen("a.in","r",stdin);
 84     freopen("a.out","w",stdout);
 85     int n;
 86     scanf("%d",&n);
 87     st=n*n+n+1,ed=st+1;
 88     len=0;
 89     memset(first,0,sizeof(first));
 90     ans=0;
 91     for(int i=1;i<=n;i++)
 92      for(int j=1;j<=n;j++)
 93      {
 94          int x;
 95          scanf("%d",&x);
 96          ins(st,n*(i-1)+j,x);
 97          ans+=x;
 98          ins(n*(i-1)+j,n*n+i,INF);
 99          ins(n*(i-1)+j,n*n+j,INF);
100      }
101     for(int i=1;i<=n;i++)
102     {
103         int x;
104         scanf("%d",&x);
105         ins(n*n+i,ed,x);
106     }
107     max_flow();
108     printf("%d\n",ans);
109     return 0;
110 }
View Code

 

2017-03-24 08:40:32

 

posted @ 2017-03-24 08:36  konjak魔芋  阅读(285)  评论(0编辑  收藏  举报