【BZOJ3996】【TJOI2015】线性代数 最小割

来源:互联网 发布:php contains 编辑:程序博客网 时间:2024/06/06 19:21

链接:

#include <stdio.h>int main(){    puts("转载请注明出处[vmurder]谢谢");    puts("网址:blog.csdn.net/vmurder/article/details/45200381");}

题解:

题意部分注释:最终的矩阵 D 长宽都1,所以其实要求的是一个数
首先 (A×BC×AT=A×B×ATC×AT
然后发现
左边式子 AiATj 都选的时候才会得到 Bi,j 的价值
如果 ATi 是1,那么就会损失 Ci 的价值。

这是个裸的最小割模型。

代码:

#include <queue>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define N 260000#define M 1600000#define inf 0x3f3f3f3fusing namespace std;struct Eli{    int v,len,next;}e[M];int head[N],cnt;inline void add(int u,int v,int len){    e[++cnt].v=v;    e[cnt].len=len;    e[cnt].next=head[u];    head[u]=cnt;}inline void Add(int u,int v,int len){    add(u,v,len),add(v,u,0);}queue<int>q;int d[N],s,t;bool bfs(){    while(!q.empty())q.pop();    memset(d,0,sizeof d);    int i,u,v;    q.push(s),d[s]=1;    while(!q.empty())    {        u=q.front(),q.pop();        for(i=head[u];i;i=e[i].next)        {            if(!d[v=e[i].v]&&e[i].len)            {                d[v]=d[u]+1;                if(v==t)return 1;                q.push(v);            }        }    }    return 0;}int dinic(int x,int flow){    if(x==t)return flow;    int i,u,v,k,remain=flow;    for(i=head[x];i&&remain;i=e[i].next)    {        if(d[v=e[i].v]==d[x]+1&&e[i].len)        {            k=dinic(v,min(e[i].len,remain));            if(!k)d[v]=0;            e[i].len-=k,e[i^1].len+=k;            remain-=k;        }    }    return flow-remain;}int n,maxflow,id;void build(){    int i,j,k;    int a,b,c;    scanf("%d",&n);    cnt=1,s=0,t=n*n+n+1,id=n;    for(i=1;i<=n;i++)for(j=1;j<=n;j++)    {        scanf("%d",&k);        maxflow+=k,id++;        Add(s,id,k),Add(id,i,inf),Add(id,j,inf);    }    for(i=1;i<=n;i++)    {        scanf("%d",&k);        Add(i,t,k);    }}int main(){    build();    while(bfs())maxflow-=dinic(s,inf);    cout<<maxflow<<endl;    return 0;}
0 0