zoukankan      html  css  js  c++  java
  • 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
    ",SUM-net::maxflow());   
        return 0; 
    }
    

      

  • 相关阅读:
    web在线智能四则运算挑战赛
    超简单的实现wordcount
    构建之法现代软件工程自我介绍
    通过WMI获取机器信息
    ManagementObjectSearcher Path
    开启FIPS协议
    Windows Server 2012开启多人远程
    开发企业应用系统需要掌握的知识技能
    Win7系统下彻底删除无用服务的方法
    C#基础(二)之数据类型
  • 原文地址:https://www.cnblogs.com/guangheli/p/12575373.html
Copyright © 2011-2022 走看看