[BZOJ3996]TJOI2015線性代數|最小割

  一開始沒看到是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 0x3fffffff
using 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));
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章