【BZOJ 3996】 3996: [TJOI2015]线性代数 (最小割)
3996: [TJOI2015]线性代数
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 1368 Solved: 832Description
给出一个N*N的矩阵B和一个1*N的矩阵C。求出一个1*N的01矩阵A.使得
D=(A*B-C)*A^T最大。其中A^T为A的转置。输出DInput
第一行输入一个整数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 7Sample Output
2HINT
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 }
2017-03-24 08:40:32