zoukankan      html  css  js  c++  java
  • BZOJ4873 寿司餐厅

    最大权闭合子图。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=105;
    const int M=2e5;
    int l=1,pre[M],other[M],last[M],cap[M],SUM,n,m,maxa;
    int idw[N][N],S,T,ida[N*10],a[N],w[N][N],d[M],tot;
    void add(int x,int y,int w)
    {
        ++l;pre[l]=last[x];last[x]=l;
        other[l]=y;cap[l]=w;
        ++l;pre[l]=last[y];last[y]=l;
        other[l]=x;cap[l]=0;
    }
    void work(int x,int w)
    {
        if(w<0) add(x,T,-w);
        else SUM+=w,add(S,x,w);
    }
    bool bfs()
    {
        queue<int> q;
        memset(d,0,sizeof d);
        d[S]=1;q.push(S);
        while(!q.empty())
        {
            int u=q.front();q.pop();
            for(int p=last[u];p;p=pre[p])
            {
                int v=other[p];
                if(d[v]||!cap[p]) continue;
                d[v]=d[u]+1;
                q.push(v);
            }
        }
        if(d[T]) return 1;
        return 0;
    }
    int dfs(int x,int flow)
    {
        if(x==T) return flow;
        if(!flow) return 0;
        int res=flow;
        for(int p=last[x];p;p=pre[p])
        {
            int y=other[p];
            if(cap[p]==0||d[y]!=d[x]+1) continue;
            int tmp=dfs(y,min(res,cap[p]));
            res-=tmp;
            cap[p]-=tmp;
            cap[p^1]+=tmp;
            if(tmp==0) d[y]=0;
            if(res==0) break;
        }
        return flow-res;
    }
    int dinic()
    {
        int ans=0;
        while(bfs()) ans+=dfs(S,1e9);
        return ans;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i) 
        scanf("%d",a+i),maxa=max(maxa,a[i]);
        for(int i=1;i<=n;++i)
            for(int j=i;j<=n;++j)
            scanf("%d",&w[i][j]),idw[i][j]=++tot;
        for(int i=1;i<=maxa;++i) ida[i]=++tot;
        S=tot+1;T=tot+2;
        for(int i=1;i<=n;++i)
            for(int j=i;j<=n;++j)
            if(i==j) work(idw[i][j],w[i][j]-a[i]);
            else 
            {
                work(idw[i][j],w[i][j]);
                add(idw[i][j],idw[i+1][j],1<<30);
                add(idw[i][j],idw[i][j-1],1<<30);
            }
        for(int i=1;i<=maxa;++i) work(ida[i],-m*i*i);
        for(int i=1;i<=n;++i) add(idw[i][i],ida[a[i]],1<<30);
        SUM-=dinic();
        cout<<SUM;
    }
  • 相关阅读:
    实验四 决策树
    实验三 朴素贝叶斯
    实验2 k近邻
    实验一
    实验三
    第二次实验
    实验一
    ATM取款系统
    流程图与活动图的区别与联系
    第一次随笔
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8446022.html
Copyright © 2011-2022 走看看