• LOJ #2196「SDOI2014」LIS


    直接退流复杂度好优越啊

    LOJ #2196


    题意

    一段数列,每个点有点权$ A_i$,删除代价$ B_i$,附加属性$ C_i$

    求最小代价使得$ LIS$长度发生变化,且输出一种$ C_i$字典序最小的方案


    $ Solution$

    首先可以求出以每个点结尾的$ LIS$长度数组$ f_i$

    按照套路建图

    $ i向i+n$连边权为删除代价的边

    若$ f_i$=1则$ S向i$连边权为$ INF$的边

    若$ f_i$=$ans$则 $i+n向T$连边权为$ INF$的边

    然后最小割即是答案

    跑一遍最大流即可

    考虑输出方案

    我们按$ C_i$从小到大枚举每条边,判断这条边是否是割边

    若是则选它并删除这条边的贡献

    删除之后不需要重新流一遍

    只需要从$ i$向$ S$流一遍再从$T$向$ i+n$流一遍去掉贡献

    最后再把边的流量上限改成$ 0$即可

    复杂度可能是$ O(n^3)$的?


    $ my code$

    #include<ctime>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #define INF 1000000000
    #define M 1000010
    #define rt register int
    #define ll long long
    using namespace std;
    inline ll read(){
        ll x = 0; char zf = 1; char ch = getchar();
        while (ch != '-' && !isdigit(ch)) ch = getchar();
        if (ch == '-') zf = -1, ch = getchar();
        while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar(); return x * zf;
    }
    void write(ll y){if(y<0)putchar('-'),y=-y;if(y>9)write(y/10);putchar(y%10+48);}
    void writeln(const ll y){write(y);putchar('
    ');}
    int i,j,k,m,n,x,y,z,cnt,sum,S,T;
    int A[710],B[710],f[710];
    int F[M],N[M],L[M],a[M],c[M],dis[M],cur[M],Gap[M];
    void add(int x,int y,int z){
        a[++k]=y;c[k]=z;
        if(!F[x])F[x]=k;
        else N[L[x]]=k;
        L[x]=k;
    }
    int q[M],h,t;
    bool BFS(int S,int T){
        h=0;q[t=1]=S;
        memset(dis,10,4*sum+4);memcpy(cur,F,4*sum+4);
        dis[S]=0;
        while(h<t){
            int x=q[++h];
            for(rt i=F[x];i;i=N[i])if(c[i]&&dis[a[i]]>sum){
                q[++t]=a[i];
                dis[a[i]]=dis[x]+1;
                if(a[i]==T)return 1;
            }
        }
        return 0;
    }
    int dfs(int x,int y,int flow){
        int used=0;
        if(x==y)return flow;
        for(rt i=cur[x];i;i=cur[x]=N[i])if(c[i]&&dis[x]+1==dis[a[i]]){
            int v=dfs(a[i],y,min(flow-used,c[i]));
            if(!v)continue;
            c[i]-=v;c[i^1]+=v;used+=v;
            if(used>=flow)return used;
        }
        if(!--Gap[dis[x]])dis[S]=sum+1;
        ++Gap[++dis[S]];
        return used;
    }
    int dinic(int S,int T){
        int ans=0,now;Gap[0]=sum;
        while(BFS(S,T)){
            memset(dis,0,sizeof(dis));
            while(now=dfs(S,T,INF))ans+=now;
        }
        return ans;
    }
    struct node{
        int x,val;
        bool operator <(const node s)const{
            return val<s.val;
        }
    }C[705];
    int ans[705],tot;
    int main(){
        for(rt QAQ=read();QAQ;QAQ--){
            for(rt i=1;i<=sum;i++)F[i]=0;
            for(rt i=1;i<=k;i++)L[i]=N[i]=0;
            n=read();k=1;
            for(rt i=1;i<=n;i++)A[i]=read();
            for(rt i=1;i<=n;i++)B[i]=read();
            for(rt i=1;i<=n;i++)C[i].val=read(),C[i].x=i;
            for(rt i=1;i<=n;i++)f[i]=1;
            for(rt i=2;i<=n;i++)
            for(rt j=1;j<i;j++)if(A[i]>A[j])f[i]=max(f[i],f[j]+1);
            
            int maxf=*max_element(f+1,f+n+1);
            for(rt i=1;i<=n;i++)add(i,i+n,B[i]),add(i+n,i,0);
            sort(C+1,C+n+1);S=n*2+1,sum=T=n*2+2;
            
            for(rt i=1;i<=n;i++)
            for(rt j=i+1;j<=n;j++)if(f[j]==f[i]+1)add(i+n,j,INF),add(j,i+n,0);
            for(rt i=1;i<=n;i++)if(f[i]==1)add(S,i,INF),add(i,S,0);
            for(rt i=1;i<=n;i++)if(f[i]==maxf)add(i+n,T,INF),add(T,i+n,0);
            write(dinic(S,T));putchar(' ');
            
            tot=0;
            for(rt i=1;i<=n;i++)if(!BFS(C[i].x,C[i].x+n)){
                c[C[i].x<<1]=c[C[i].x<<1|1]=0;
                dinic(T,C[i].x+n);dinic(C[i].x,S);
                ans[++tot]=C[i].x;
            }
            sort(ans+1,ans+tot+1);writeln(tot);
            for(rt i=1;i<=tot;i++)write(ans[i]),putchar(' ');putchar('
    ');
        }
        return 0;
    }
  • 相关阅读:
    The Single Responsibility Principle
    MSComDlg.CommonDialogserver不能创建对象错误的解决
    Hadoop的HA机制(Zookeeper集群+Hadoop集群)配置记录
    linux怎样查看port被谁占用
    hadoop配置说明
    C#中的继承与多态还有接口
    MySQL DATE_FORMAT() 函数
    MySQL处理数据库和表的常用命令
    mysql 增加用户
    sql2008连接数据库问题
  • 原文地址:https://www.cnblogs.com/DreamlessDreams/p/10081980.html
Copyright © 2020-2023  润新知