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