[BZOJ3996]TJOI2015线性代数|最小割

来源:互联网 发布:网络广告语 编辑:程序博客网 时间:2024/06/05 06:23

  一开始没看到是01矩阵。。化简之后发现 ,

D=i=1nj=1na[i]a[j]b[i][j]i=1na[i]c[i]
那么也就是相当于有n个物品,选了i和j可以得到b[i][j]的收益,但是选i要付出c[i]的代价,经典的最大权闭合子图模型。。

#include<cstdio>#include<iostream>#define N 505*505#define M 505*505*6#define inf 0x3fffffffusing namespace std;struct edge{    int e,f,next;} ed[M];int n,i,j,ne=1,nd,sum=0,a[N],d[N],que[N],u[N];void add(int s,int e,int f){    ed[++ne].e=e;ed[ne].f=f;    ed[ne].next=a[s];a[s]=ne;}void ins(int s,int e,int f){    add(s,e,f);add(e,s,0);}bool bfs(int s,int t){    int get,head=1,tail=1,j;    for (int i=0;i<=nd;i++) u[i]=0;    d[s]=0;u[s]=1;que[1]=s;d[t]=0;    while (head<=tail)    {        get=que[head++];        for (j=a[get];j;j=ed[j].next)            if (ed[j].f&&!u[ed[j].e])            {                d[ed[j].e]=d[get]+1;                que[++tail]=ed[j].e;                u[ed[j].e]=1;            }    }    return d[t]!=0;}int extend(int x,int minf,int t){    if (x==t) return minf;    int del,f=minf;    for (int j=a[x];j;j=ed[j].next)        if (ed[j].f&&d[ed[j].e]==d[x]+1)        {            del=extend(ed[j].e,min(minf,ed[j].f),t);            ed[j].f-=del;ed[j^1].f+=del;            minf-=del;            if (!minf) break;        }    if (f==minf) d[x]=0;    return f-minf;}int dinic(int s,int t){    int ans=0;    while(bfs(s,t)) ans+=extend(s,inf,t);    return ans;}int main(){    scanf("%d",&n);    nd=n*n+n+1;    for (i=1;i<=n;i++)        for (j=1;j<=n;j++)        {            int q;scanf("%d",&q);            ins(0,(i-1)*n+j,q);            ins((i-1)*n+j,n*n+i,inf);ins((i-1)*n+j,n*n+j,inf);            sum+=q;        }    for (i=1;i<=n;i++)    {        int q;scanf("%d",&q);        ins(n*n+i,nd,q);    }    printf("%d\n",sum-dinic(0,nd));}
0 0
原创粉丝点击