BZOJ 4873: [Shoi2017]寿司餐厅 最大权闭合图

比较好想的建模题.   

显然,如果选 $[l,r]$ 的话只要强制选 $[l,r-1]$ 与 $[l+1,r]$ 就行了. 

然后 $m=0$ 的话直接在 $[i,i]$ 上扣掉编号大小就行. 

如果 $m=1$,就套路的新建一个点,然后练一下限制的编号就行了. 

code: 

#include <bits/stdc++.h>  
#define N 20006  
#define M 103          
#define I(s) freopen(s".in","r",stdin) 
#define O(s) freopen(s".out","w",stdout)
#define setIO(s) I(s)       
using namespace std;       
const int inf=2000000001;       
namespace net
{
    struct Edge   
    {
        int u,v;
        int c;
        Edge(int u=0,int v=0,int c=0):u(u),v(v),c(c){}
    };
    queue<int>q;
    vector<Edge>edges;
    vector<int>G[N];
    int vv[N],vis[N],d[N],bo[N],s,t;    
    void add(int u,int v,int c)
    {
        edges.push_back(Edge(u,v,c));
        edges.push_back(Edge(v,u,0));
        int o=edges.size();
        G[u].push_back(o-2);
        G[v].push_back(o-1);   
    } 
    int dfs(int x,int cur)
    {
        if(x==t)
            return cur;
        int an=0,flow=0;
        for(int i=vv[x];i<G[x].size();++i,++vv[x])    
        {
            Edge e=edges[G[x][i]];
            if(e.c>0&&d[e.v]==d[x]+1)
            {  
                an=dfs(e.v,min(cur,e.c));
                if(an)
                {
                    cur-=an;
                    flow+=an;         
                    edges[G[x][i]].c-=an;
                    edges[G[x][i]^1].c+=an; 
                    if(!cur)
                        break;
                }
            }
        }
        return flow;
    }
    int bfs()
    { 
        memset(vis,0,sizeof(vis));
        d[s]=0;
        vis[s]=1;
        q.push(s);
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int i=0;i<G[u].size();++i)
            {
                if(edges[G[u][i]].c>0)
                {
                    int v=edges[G[u][i]].v;
                    if(!vis[v])
                    {
                        vis[v]=1;
                        d[v]=d[u]+1;
                        q.push(v);
                    }
                }
            }
        }
        return vis[t];
    }
    int maxflow()
    {
        int re=0;
        while(bfs())
        {
            memset(vv,0,sizeof(vv));        
            re+=(int)dfs(s,inf);
        }
        return re;
    }          
};   
int a[N],val[M][M],id[M][M];   
vector<int>G[N];  
int main() 
{  
    // setIO("input");       
    int n,m,tim=0;    
    scanf("%d%d",&n,&m);     
    for(int i=1;i<=n;++i) 
    {  
        scanf("%d",&a[i]);   
        G[a[i]].push_back(i);   
    }
    for(int i=1;i<=n;++i) 
    {
        for(int j=i;j<=n;++j) 
            scanf("%d",&val[i][j]),id[i][j]=++tim;    
    }    
    for(int i=1;i<=n;++i)   
        val[i][i]-=a[i];              
    int s=0,t=n*n+n+2,SUM=0;   
    net::s=s,net::t=t;  
    for(int i=1;i<=n;++i) 
    {   
        for(int j=i;j<=n;++j) 
        {    
            if(j>i)   
            {
                net::add(id[i][j],id[i+1][j],inf);   
                net::add(id[i][j],id[i][j-1],inf);   
            }  
            if(val[i][j]>0)  
            { 
                SUM+=val[i][j];   
                net::add(s,id[i][j],val[i][j]);   
            }
            else 
            {
                net::add(id[i][j],t,-val[i][j]);   
            }
        }   
    } 
    for(int i=0;i<=1000;++i) 
    {
        if(G[i].size()) 
        {
            ++tim;     
            net::add(tim,t,m*i*i);     
            for(int j=0;j<G[i].size();++j) 
            {
                int y=G[i][j];    
                net::add(id[y][y],tim,inf);     
            }
        }
    }
    printf("%d\n",SUM-net::maxflow());   
    return 0; 
}

  

posted @ 2020-03-26 16:40  EM-LGH  阅读(94)  评论(0编辑  收藏  举报