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

Solution

没有发现选择一个$a_i$就将花费$c_i$,选择$a_i$和$a_j$将收益$b_{i,j}$,然后就成了最大权闭合子图了。

Code

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<queue>
 5 #define N (1009)
 6 using namespace std;
 7 
 8 struct Edge{int to,next,flow;}edge[2*N*N];
 9 int n,b[N][N],c[N],Depth[2*N*N],INF,s,e=1e6,sum;
10 int head[2*N*N],num_edge;
11 queue<int>q;
12 
13 void add(int u,int v,int l)
14 {
15     edge[++num_edge].to=v;
16     edge[num_edge].next=head[u];
17     edge[num_edge].flow=l;
18     head[u]=num_edge;
19 }
20 
21 int DFS(int x,int low)
22 {
23     if (x==e || !low) return low;
24     int f=0;
25     for (int i=head[x]; i; i=edge[i].next)
26         if (Depth[edge[i].to]==Depth[x]+1)
27         {
28             int Min=DFS(edge[i].to,min(low,edge[i].flow));
29             edge[i].flow-=Min;
30             edge[((i-1)^1)+1].flow+=Min;
31             f+=Min; low-=Min;
32             if (!low) break;
33         }
34     if (!f) Depth[x]=-1;
35     return f;
36 }
37 
38 bool BFS(int s,int e)
39 {
40     memset(Depth,0,sizeof(Depth));
41     Depth[s]=1; q.push(s);
42     while (!q.empty())
43     {
44         int x=q.front(); q.pop();
45         for (int i=head[x]; i; i=edge[i].next)
46             if (!Depth[edge[i].to] && edge[i].flow)
47             {
48                 Depth[edge[i].to]=Depth[x]+1;
49                 q.push(edge[i].to);
50             }
51     }
52     return Depth[e];
53 }
54 
55 int Dinic(int s,int e)
56 {
57     int ans=0;
58     while (BFS(s,e))
59         ans+=DFS(s,INF);
60     return ans;
61 }
62 
63 int main()
64 {
65     memset(&INF,0x7f,sizeof(INF));
66     scanf("%d",&n);
67     for (int i=1; i<=n; ++i)
68         for (int j=1; j<=n; ++j)
69             scanf("%d",&b[i][j]), sum+=b[i][j];
70     for (int i=1; i<=n; ++i)
71         scanf("%d",&c[i]);
72     for (int i=1; i<=n; ++i)
73         for (int j=1; j<=n; ++j)
74         {
75             add(s,(i-1)*n+j,b[i][j]);
76             add((i-1)*n+j,s,0);
77         }
78     for (int i=1; i<=n; ++i)
79         for (int j=1; j<=n; ++j)
80         {
81             add((i-1)*n+j,n*n+i,INF);
82             add(n*n+i,(i-1)*n+j,0);
83             add((i-1)*n+j,n*n+j,INF);
84             add(n*n+j,(i-1)*n+j,0);
85         }
86     for (int i=1; i<=n; ++i)
87     {
88         add(n*n+i,e,c[i]);
89         add(e,n*n+i,0);
90     }
91     printf("%d\n",sum-Dinic(s,e));
92 }
posted @ 2019-01-18 16:31  Refun  阅读(212)  评论(0编辑  收藏  举报