3996: [TJOI2015]线性代数
Time Limit: 10 SecMemory Limit: 128 MB
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
【题解】
花了好久时间化简,最后化简出来是
我们发现,a是一个01矩阵,然后其实就可以化成这么一个问题:
有n个东西,选了i,j两件东西能得到b[i,j]的价值,然而选i需要c[i]的花费,选j需要c[j]的花费……
据大聚聚们说,这是一个经典的最小割模型。
建立S,T。
S连(i,j)边,边权为b[i,j],(i,j)连i、连j边,边权均为∞,i向T连边,边权为c[i]。
然后求最小割,最后答案就是
sum(b[i][j])-最小割答案 (i∈[1..n],j∈[1..n])
最小割今天早上刚写过dinic哈哈=-=
然而第一次写边链表,好在也AC了
STL的queue被卡RE了 TAT好可怕要自己写队列了
然后了一堆地方有bug调了一个小时
1 #include<iostream> 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<string.h> 5 #include<algorithm> 6 #include<math.h> 7 #include<string> 8 using namespace std; 9 const int inf=210000; 10 int c[250510],head[250510]; 11 long long ans; 12 int q[250510]; 13 int s,t,n,tt,heads,tail; 14 struct edge { 15 int next,num,x; 16 }e[2505010]; 17 int read2() { 18 int x=0; int f=1; 19 char ch=getchar(); 20 while(ch<‘0‘||ch>‘9‘) {if(ch==‘-‘) f=-1; ch=getchar();} 21 while(ch>=‘0‘&&ch<=‘9‘) {x=(x<<3)+(x<<1)+ch-‘0‘; ch=getchar();} 22 return x*f; 23 } 24 inline void f(int a,int b,int w) { 25 e[++tt].next=head[a];head[a]=tt; 26 e[tt].num=w;e[tt].x=b; 27 e[++tt].next=head[b];head[b]=tt; 28 e[tt].num=0;e[tt].x=a; 29 } 30 bool bfs() { 31 for (int i=s;i<=t;++i) c[i]=0; 32 heads=tail=1; 33 q[tail]=s;c[s]=1; 34 while(heads<=tail) { 35 int top=q[heads++]; 36 for (int i=head[top];i;i=e[i].next) { 37 int x=e[i].x,num=e[i].num; 38 if(num==0||c[x]>0) continue; 39 c[x]=c[top]+1; 40 q[++tail]=x; 41 if(x==t) return 1; 42 } 43 } 44 return 0; 45 } 46 int dfs(int y,int low) { 47 if(y==t) return low; 48 int flow,r=low; 49 for (int i=head[y];i;i=e[i].next) { 50 int x=e[i].x,num=e[i].num; 51 if(c[x]!=c[y]+1 || num==0) continue; 52 flow=dfs(x,min(r,num)); 53 r-=flow; 54 e[i].num-=flow; e[i^1].num+=flow; 55 if(!r) return low; 56 } 57 if(r==low) c[y]=-1; 58 return low-r; 59 } 60 int main() { 61 //freopen("algebra.in","r",stdin); 62 //freopen("algebra.out","w",stdout); 63 int k,w; 64 n=read2();s=0,t=n*n+n+1; k=n; 65 for (int i=1;i<=n;++i) 66 for (int j=1;j<=n;++j) { 67 w=read2(); 68 ans+=w; 69 f(s,++k,w); 70 f(k,i,inf); 71 f(k,j,inf); 72 } 73 for (int i=1;i<=n;++i) { 74 w=read2(); 75 f(i,t,w); 76 } 77 while(bfs()) ans-=dfs(s,inf); 78 cout<<ans<<endl; 79 //fclose(stdin); 80 //fclose(stdout); 81 return 0; 82 }
这是我在BZOJ AC的第10题,仅此纪念 2015/6/12
时间: 2024-10-11 16:42:13