bzoj3996 [TJOI2015]线性代数
2017-03-31 11:37
211 查看
题目链接:bzoj3996
题目大意:
给出一个N*N的矩阵B和一个1*N的矩阵C。求出一个1*N的01矩阵A.使得
D=(A*B-C)*A^T最大。其中A^T为A的转置。输出D
题解:
最小割
据题意最后可以化出D=∑i=1N∑j=1Naiajbij−∑i=1Naici
于是就是经典网络流模型QwQ???被D了一波后跑来写题解orzorzorz
套路就是先把正权加到答案里,跑网络流,减掉损失。
有两种构图方式:
1、把b和a都建出来:
对于一个bij来说,若aiaj都选的话那就要割掉ci和cj,不然就要割掉bij。
2、只建a
- S→i,流量为ci
对于一对点(i,j),设i<j
- i→T,流量为bij+bji。
- j→i,流量为bij+bji。
为什么呢
我们先来编个号左边表示选,右边表示不选
对于这样的一种情况有4种割法:12、56、136、245
而除了12这种割法外,其他都会产生一定的损失即bij+bji
所以我们给3、5或4、6那么多的流量,即使除12这种割法外的其他割法都有且只有bij+bji的损失。
噢,不要忘了bii
↓这个是第一种构图的
第二种的代码看栋爷爷的好了..膜膜膜感谢栋爷爷跟我一起搞这题戳我戳我
问奥爷爷第二种构图の小剧场:
我:奥爷爷为什么要这样构图啊
奥爷爷:这不是很显然的吗?
我:啊..怎么显然了?
奥爷爷:看出来啊
我:…怎么看啊
奥爷爷:用眼睛啊
[我:…….How much I can say?感觉又被D了一波
题目大意:
给出一个N*N的矩阵B和一个1*N的矩阵C。求出一个1*N的01矩阵A.使得
D=(A*B-C)*A^T最大。其中A^T为A的转置。输出D
题解:
最小割
据题意最后可以化出D=∑i=1N∑j=1Naiajbij−∑i=1Naici
于是就是经典网络流模型QwQ???被D了一波后跑来写题解orzorzorz
套路就是先把正权加到答案里,跑网络流,减掉损失。
有两种构图方式:
1、把b和a都建出来:
对于一个bij来说,若aiaj都选的话那就要割掉ci和cj,不然就要割掉bij。
2、只建a
- S→i,流量为ci
对于一对点(i,j),设i<j
- i→T,流量为bij+bji。
- j→i,流量为bij+bji。
为什么呢
我们先来编个号左边表示选,右边表示不选
对于这样的一种情况有4种割法:12、56、136、245
而除了12这种割法外,其他都会产生一定的损失即bij+bji
所以我们给3、5或4、6那么多的流量,即使除12这种割法外的其他割法都有且只有bij+bji的损失。
噢,不要忘了bii
↓这个是第一种构图的
/************************************************************** Problem: 3996 User: 564415605 Language: C++ Result: Accepted Time:2024 ms Memory:53148 kb ****************************************************************/ #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define maxn 300010 #define inf 0x7fffffff struct node { int y,c,next,ot; }a[maxn*10];int len,first[maxn]; int d[maxn],list[maxn*2],head,tail,S,T; bool vis[maxn]; int mymin(int x,int y) {return (x<y)?x:y;} void ins(int x,int y,int c) { len++;int now1=len; a[len].y=y;a[len].c=c; a[len].next=first[x];first[x]=len; len++;int now2=len; a[len].y=x;a[len].c=0; a[len].next=first[y];first[y]=len; a[now1].ot=now2;a[now2].ot=now1; } bool bfs() { head=1;tail=2; memset(d,-1,sizeof(d)); memset(vis,false,sizeof(vis)); d[S]=1;list[head]=S;vis[S]=true; while (head!=tail) { int x=list[head]; for (int k=first[x];k!=-1;k=a[k].next) { int y=a[k].y; if (d[y]==-1 && a[k].c>0) { d[y]=d[x]+1; if (!vis[y]) { list[tail++]=y; if (tail>T*2) tail=1; vis[y]=true; } } }vis[x]=false; head++; if (head>T*2) head=1; } return d[T]>0; } int dfs(int x,int flow) { if (x==T) return flow; int minf=0; for (int k=first[x];k!=-1;k=a[k].next) { int y=a[k].y; if (d[y]==d[x]+1 && a[k].c>0) { int p=mymin(flow-minf,a[k].c); p=dfs(y,p); a[k].c-=p; a[a[k].ot].c+=p; minf+=p; if (minf==flow) break; } } if (minf==0) d[x]=0; return minf; } int dinic() { int ret=0; while (bfs()) ret+=dfs(S,inf); return ret; } int main() { int n,i,j,ls,x,ans=0; len=0;memset(first,-1,sizeof(first)); scanf("%d",&n);ls=n*n; S=n*(n+1)+1;T=S+1; for (i=1;i<=n;i++) for (j=1;j<=n;j++) { scanf("%d",&x); ins(S,(i-1)*n+j,x); ins((i-1)*n+j,ls+i,inf); ins((i-1)*n+j,ls+j,inf); ans+=x; } for (i=1;i<=n;i++) { scanf("%d",&x); ins(ls+i,T,x); } printf("%d\n",ans-dinic()); return 0; }
第二种的代码看栋爷爷的好了..膜膜膜感谢栋爷爷跟我一起搞这题戳我戳我
问奥爷爷第二种构图の小剧场:
我:奥爷爷为什么要这样构图啊
奥爷爷:这不是很显然的吗?
我:啊..怎么显然了?
奥爷爷:看出来啊
我:…怎么看啊
奥爷爷:用眼睛啊
[我:…….How much I can say?感觉又被D了一波
相关文章推荐
- bzoj 3996: [TJOI2015]线性代数
- BZOJ3996 [TJOI2015]线性代数 【最小割】
- BZOJ 3996 [TJOI 2015] 线性代数 解题报告
- 【BZOJ】3996: [TJOI2015]线性代数
- bzoj3996 [TJOI2015]线性代数
- bzoj3996 [TJOI2015]线性代数
- bzoj 3996: [TJOI2015]线性代数
- ●BZOJ 3996 [TJOI2015]线性代数
- 3996: [TJOI2015]线性代数
- 【BZOJ】【TJOI2015】线性代数
- BZOJ 3996: [TJOI2015]线性代数(最大权闭合子图)
- bzoj3996 [TJOI2015]线性代数(最小割)
- BZOJ 3996 TJOI2015 线性代数 网络流
- 【bzoj3996】[TJOI2015]线性代数
- BZOJ3996: [TJOI2015]线性代数
- BZOJ3996 [TJOI2015]线性代数
- bzoj 3996: [TJOI2015]线性代数 [最小割]
- 【bzoj3996】【TJOI2015】【线性代数】【最小割】
- BZOJ 3996: [TJOI2015]线性代数 最大权闭合子图 最小割
- 【bzoj3996】[TJOI2015]线性代数 最大权闭合图