• 「六省联考 2017」寿司餐厅


    题目链接

    戳我

    (Describe)

    简要题目:
    一个序列,可以若干次取其中一段区间,区间及其子集的价值都会被统计进去且每个区间的价值只能被统计一次。
    如果你拿(c)(x)数,你需要花费(m*x^2+c*x)的代价。
    求最大价值。

    (Solution)

    这道题看起来并没有思路,看了看题解后发现这是最大权闭合子图。(What?)这是神马?不会,于是去学了一下。

    然后发现这道题就是最大权闭合子图;

    首先处理区间:
    将区间看成点,看看这个区间的权值是否为正,为正用(S)和这个区间相连,流量为权值。反之用这个区间和(t)相连流量为权值的前缀和。因为对于一个区间他还必须要包括子区间,所以我们在把这个区间([i,j])([i,j-1],[i+1,j])相连。流量为(inf)

    再来看看寿司

    对于(m*x^2+c*x)我们将他拆分。变成(m*x^2)(c*x)

    对于(m*x^2)我们会发现他和数量没冠希,于是我们可以将他和(T)相连流量为(m*x^2)
    在将([i,i])这个点和这个寿司相连,流量为(inf)再将这个点和(T)相连流量为(x)

    (Code)

    #include<bits/stdc++.h>
    #define inf 1e9
    using namespace std;
    typedef long long ll;
    int read(){
        int x=0,f=1;
        char c=getchar();
        while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
        while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
        return x*f;
    }
    struct node{
        int to,next,v;
    }a[200001];
    int head[100001],cnt,n,m,s,t,x,y,z,dep[100001],ans,cur[100001];
    void add(int x,int y,int c){
        a[++cnt].to=y,a[cnt].next=head[x],a[cnt].v=c,head[x]=cnt;
        a[++cnt].to=x,a[cnt].next=head[y],a[cnt].v=0,head[y]=cnt;
    }
    queue<int> q;
    int bfs(){
        memset(dep,0,sizeof(dep));
        q.push(s),dep[s]=1;
        while(!q.empty()){
            int now=q.front();
            q.pop();
            for(int i=head[now];i;i=a[i].next){
                int v=a[i].to;
                if(!dep[v]&&a[i].v)
                    q.push(v),dep[v]=dep[now]+1;
            }
        }
        if(dep[t]!=0)
            return 1;
        else
            return 0;
    }
    int dfs(int k,int list){
        if(k==t)
            return list;
        for(int & i=cur[k];i;i=a[i].next){
            int v=a[i].to;
            if(a[i].v&&dep[v]==dep[k]+1){
                int p=dfs(v,min(list,a[i].v));
                if(p){
                    a[i].v-=p;
                    if(i%2)
                        a[i+1].v+=p;
                    else
                        a[i-1].v+=p;
                    return p;
                }
            }
        }
        return 0;
    }
    int Dinic(){
        int ans=0;
        while(bfs()){
            for(int i=s;i<=t;i++)
                cur[i]=head[i];
            int k=dfs(s,2147483);
            while(k)
                ans+=k,k=dfs(s,2147483);
        }
        return ans;
    }
    int vis[1001][1001],bj[1001],f[1001][1001];
    int main(){
        n=read(),m=read(),s=0,t=50000,ans=0;
        for(int i=1;i<=n;i++)
            for(int j=i;j<=n;j++)
                f[i][j]=(i-1)*n+j+3000;
        for(int i=1;i<=n;i++){
            x=read();
            if(!bj[x])
                add(x,t,x*x*m);
            add(f[i][i],x,inf);
            add(f[i][i],t,x);
            bj[x]=1;
        }
        for(int i=1;i<=n;i++)
            for(int j=i;j<=n;j++){
                x=read();
                if(x>0)
                    ans+=x,add(s,f[i][j],x);
                else
                    add(f[i][j],t,-x);
                if(i!=j)
                    add(f[i][j],f[i+1][j],inf),add(f[i][j],f[i][j-1],inf);
            }
        printf("%d
    ",ans-Dinic());
    }
    
  • 相关阅读:
    C# DES加密和解密
    SQL设计技巧优化
    MS15-034漏洞技术研究
    Vustudy靶场环境快速搭建
    FastJson<=1.2.47漏洞复现
    多台电脑共享一套鼠键--Mouse Without Borders
    {Java初级系列四}---继承、接口和抽象类
    {Java初级系列三}---面向对象和类
    {Java初级系列二}---Java类基础知识
    {Java初阶系列一}---Java基本简介
  • 原文地址:https://www.cnblogs.com/hbxblog/p/10265715.html
Copyright © 2020-2023  润新知