Description

给定序列A,序列中的每一项Ai有删除代价Bi和附加属性Ci。请删除若干项,使得4的最长上升子序列长度减少至少1,且付出的代价之和最小,并输出方案。
如果有多种方案,请输出将删去项的附加属性排序之后,字典序最小的一种。


按在上升子序列中的位置连成网络,拆点之间限流为\(b\),显然跑一波最小割最长上升子序列长度就会减一

但是字典序最小的割边要怎么找呢QAQ

如果一条正向边满流了而且在残图中这条边的起点到终点不连通那么这条边就可以是割边

当然了啊如果这条边甚至没有满流它怎么可能成为割边,如果去掉这条边还是联通那去掉了也没有什么用同样不可能是割边

然后就把序列按照c排序,把拆出来的\(n\) 条边先连上,然后一个个判断这条边是不割边。

注意判断是割边后要把这条边退流,这样的话和这条边在同一条路径上的边就不会被选重了

这样是可以保证字典序最小的,每一个长度能到达答案的上升序列都包含一个被流掉的点,贪心并不会使后面的边的选择变劣


#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define M 150000
using namespace std;

int n,m,k,t,ver[M],edge[M],head[M],nex[M],cnt=1,c[M],T,ans,cur[M],d[M],maxx,fr[M],p[M],l;
queue <int> q;

struct vv
{
    int a,b,c,w,f;
} v[M];

bool cmp(vv a,vv b) {return a.c<b.c;}
void modi(int x,int k){for(int i=x;i<=n;i+=i & -i) c[i]=max(c[i],k);}
int ask(int x){int ans=0; for(int i=x;i>0;i-=i & -i) ans=max(ans,c[i]); return ans;}
void add(int x,int y,int z)
{
    ver[++cnt]=y; nex[cnt]=head[x]; head[x]=cnt; edge[cnt]=z; fr[cnt]=x;
    ver[++cnt]=x; nex[cnt]=head[y]; head[y]=cnt; edge[cnt]=0;
}

bool bfs(int S,int T)
{
    memcpy(cur,head,sizeof(head));
    memset(d,0,sizeof(d));
    while(q.size()) q.pop();
    d[S]=1; q.push(S);
    while(q.size())
    {
        int x=q.front(); q.pop();
        for(int i=head[x];i;i=nex[i])
        if(edge[i] && !d[ver[i]])
        {
            d[ver[i]]=d[x]+1;
            if(ver[i]==T) return 1;
            q.push(ver[i]);
        }
    }
    return 0;
}

int dinic(int x,int flow,int T)
{
    if(x==T || !flow) return flow;
    int re=flow, k;
    for(int& i=cur[x];i && re;i=nex[i])
    if(edge[i] && d[ver[i]]==d[x]+1)
    {
        int k=dinic(ver[i],min(re,edge[i]),T);
        re-=k; edge[i]-=k; edge[i^1]+=k;
        if(!k) d[ver[i]]=0;
    }
    return flow-re;
}

int main()
{
    scanf("%d",&T);
    for(;T;T--)
    {
        memset(head,0,sizeof(head)); memset(nex,0,sizeof(nex));
        cnt=1, ans=maxx=l=0; memset(c,0,sizeof(c));
        scanf("%d",&n); t=2*n+1;
        for(int i=1;i<=n;i++) scanf("%d",&v[i].a);
        for(int i=1;i<=n;i++) scanf("%d",&v[i].b);
        for(int i=1;i<=n;i++) scanf("%d",&v[i].c), v[i].w=i;
        for(int i=1;i<=n;i++)
        {
            v[i].f=ask(v[i].a-1)+1; maxx=max(maxx,v[i].f);
            modi(v[i].a,v[i].f);
        }
        sort(v+1,v+1+n,cmp);
        for(int i=1;i<=n;i++) add(v[i].w,v[i].w+n,v[i].b);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++) if(v[j].w>v[i].w && v[j].f==v[i].f+1 && v[j].a>v[i].a)
                add(v[i].w+n,v[j].w,0x3f3f3f3f);
            if(v[i].f==1) add(0,v[i].w,0x3f3f3f3f);
            if(v[i].f==maxx) add(v[i].w+n,t,0x3f3f3f3f);
        }
        while(bfs(0,t)) while(k=dinic(0,0x3f3f3f3f,t)) ans+=k;
        for(int i=2;i<=n+n+2;i+=2)
        if(!edge[i] && ver[i]==fr[i]+n && fr[i]  &&!bfs(fr[i],ver[i]))
        {
            p[++l]=fr[i];
            bfs(fr[i],0); while(dinic(fr[i],edge[i^1],0));
            bfs(t,ver[i]); while(dinic(t,edge[i^1],ver[i]));
        }
        sort(p+1,p+1+l);
        printf("%d %d\n",ans,l);
        for(int i=1;i<=l;i++)  printf("%d ",p[i]);
        printf("\n");
    }
}

3532: [Sdoi2014]Lis的更多相关文章

  1. 3532: [Sdoi2014]Lis 最小字典序最小割

    3532: [Sdoi2014]Lis Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 865  Solved: 311[Submit][Status] ...

  2. BZOJ 3532: [Sdoi2014]Lis (最大流)

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3532 题意:给出三个数列ABC,长度均为n.删除A中的某些数字,使得A的最长上升子 ...

  3. BZOJ.3532.[SDOI2014]LIS(最小割ISAP 退流)

    BZOJ 洛谷 \(LIS\)..经典模型? 令\(f_i\)表示以\(i\)结尾的\(LIS\)长度. 如果\(f_i=1\),连边\((S,i,INF)\):如果\(f_i=\max\limits ...

  4. [BZOJ]3532: [Sdoi2014]Lis

    Time Limit: 10 Sec  Memory Limit: 512 MB Description 给定序列A,序列中的每一项Ai有删除代价Bi和附加属性Ci.请删除若干项,使得4的最长上升子序 ...

  5. bzoj千题计划141:bzoj3532: [Sdoi2014]Lis

    http://www.lydsy.com/JudgeOnline/problem.php?id=3532 如果没有字典序的限制,那么DP拆点最小割即可 加上字典序的限制: 按c从小到大枚举最小割边集中 ...

  6. BZOJ3532 : [Sdoi2014]Lis

    f[i]表示以i为结尾的LIS长度 对于所有f[i]=1的,由S向i连边 对于所有f[i]=maxf的,由i向T连边 对于j<i,a[j]<a[i],且f[j]+1=f[i]的,j向i连边 ...

  7. 【bzoj3532】 Sdoi2014—Lis

    http://www.lydsy.com/JudgeOnline/problem.php?id=3532 (题目链接) 题意 给出$n$个数的数列,三个值$a[i],b[i],c[i]$.将其中一些数 ...

  8. [SDOI2014]LIS

    这道题还是非常好的 首先第一问可以让我们联想到某网络流二十四题里的一道题,发现建图方式应该和这道题差不多啊 所以首先跑一遍\(dp\),求出\(dp[i]\)表示\(i\)位置结束的\(LIS\)长度 ...

  9. [bzoj3532][Sdoi2014]Lis——拆点最小割+字典序+退流

    题目大意 给定序列A,序列中的每一项Ai有删除代价Bi和附加属性Ci.请删除若 干项,使得4的最长上升子序列长度减少至少1,且付出的代价之和最小,并输出方案. 如果有多种方案,请输出将删去项的附加属性 ...

随机推荐

  1. 为什么IIS的应用池回收设置默认为1740分钟-20180720

    [非原创,个人收集,希望大家有感触] 你可曾留心过IIS的应用池回收设置默认值是多少?1740分钟对吗,那么为什么会是这样的数值呢? 在asp.net的某篇博客里提到了这个问题. 有关微软产品的许多决 ...

  2. Table转换成实体、Table转换成实体集合(可转换成对象和值类型)

    /// <summary> /// Table转换成实体 /// </summary> /// <typeparam name="T">< ...

  3. [android] fragment的动态创建

    在一个商业软件中,会有很多的界面,如果没一个界面对应一个activity,那么activity会非常的多,清单文件也会非常的乱,谷歌在android3.0以后引入了新的概念叫fragment frag ...

  4. [android] 轮播图-滑动图片标题焦点

    谷歌提供的v4包,ViewPager 在布局文件中,先添加<android.support.v4.view.ViewPager/>控件,这个只是轮播的区域 在布局文件中,布置标题描述部分 ...

  5. Java虚拟机--垃圾收集器和内存分配

    垃圾收集器和内存分配 程序计数器.虚拟机栈.本地方法栈这三个区域和线程的生命周期一致,所以方法结束或者线程结束时,内存自然就跟着回收了.Java堆和方法区,只有在程序处于运行期间才能知道会创建哪些对象 ...

  6. IntelliJ IDEA 启动tomcat服务器报Error running 'Unnamed': Address localhost:1099 is already in use错误的问题

    在使用Intellij IDEA运行web项目时,出现 :Error running Tomcat8: Address localhost:1099 is already in use,使其web项目 ...

  7. 盐水的故事(hdu1408)

    盐水的故事 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Subm ...

  8. 使用Java对字符串进行升序排序

    Java对字符串的很多API和功能是JavaWeb能广泛发展的基础,下面是一道经典的字符串操作题,需要边查JAVASE的API对每个步骤进行操作. 题目:给一个字符串,"34 12 -8 0 ...

  9. Java - "JUC" ReentrantLock获取锁

    [Java并发编程实战]-----“J.U.C”:ReentrantLock之一简介 ReentrantLock介绍 ReentrantLock是一个可重入的互斥锁,又被称为“独占锁”. 顾名思义,R ...

  10. Linux常用基本命令(cut)

    cut命令 作用:从文件的每一行剪切字节,字符或者字段,类似与编程语言中的字符串截取函数 格式:cut [option] [file] -b:仅显示行中指定直接范围的内容: -c:仅显示行中指定范围的 ...