您的位置:首页 > 其它

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

↓这个是第一种构图的

/**************************************************************
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了一波
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: