bzoj3996 [TJOI2015]线性代数

来源:互联网 发布:淘宝如何申请二次售后 编辑:程序博客网 时间:2024/05/17 23:45

题目链接:bzoj3996
题目大意:
给出一个N*N的矩阵B和一个1*N的矩阵C。求出一个1*N的01矩阵A.使得
D=(A*B-C)*A^T最大。其中A^T为A的转置。输出D

题解:
最小割
据题意最后可以化出

D=i=1Nj=1Naiajbiji=1Naici

于是就是经典网络流模型QwQ???被D了一波后跑来写题解orzorzorz
套路就是先把正权加到答案里,跑网络流,减掉损失。
有两种构图方式:
1、把ba都建出来:
这里写图片描述
对于一个bij来说,若aiaj都选的话那就要割掉cicj,不然就要割掉bij

2、只建a
- Si,流量为ci

对于一对点(i,j),设i<j
- iT,流量为bij+bji
- ji,流量为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 0x7fffffffstruct 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了一波

0 0
原创粉丝点击