正题

题目链接:https://www.luogu.com.cn/problem/P3308


题目大意

三个\(n\)个数字的序列\(A,B,C\)。要求删除其中某些位置\(i\)使得\(A\)的最长上升子序列至少减少\(1\)且删去位置\(B\)的权值和最小的情况下满足删去位置的\(C\)值升序排序后字典序最小。


解题思路

首先\(B\)值最小很好求,跑一遍\(LIS\)的\(dp\),然后每个点拆成两个点,然后如果\(f[x]\)转移到\(f[y]\)是最优的就建边然后跑最小割就好了。

大体和P2766 最长不下降子序列问题差不多

也就是现在我们要求字典序最小的最小割,需要利用到最小割的性质。

如果一条边\(x,y\)是可行割,那么它满足在残量网络上\(x\)到达不了\(y\)。

首先如果\(x->y\)没有满流那么肯定不是最小割,其次如果满流了但是还有一条\(x\)到\(y\)的路径,那么证明如果走这条增广路一定可以使最大流更大,所以也不是最小割。

那么这样我们就可以判断一条边是否可行了,然后需要消去其他等价边的影响,大体方法是从\(T\)到\(y\)跑一次\(dinic\),再从\(x\)到\(S\)跑一次\(dinic\)。这个操作叫退流,这样残量网络就变成了满流边\(x->y\)的残量网络了。

先跑一次\(dinic\),然后按照\(C\)值排序,从小到大判断加入边即可。


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#define ll long long
using namespace std;
const ll N=710*2,inf=1e18;
struct node{
ll to,next,w;
}a[N*N];
ll T,n,tot,ls[N],dep[N],A[N],B[N],C[N],f[N],p[N];
vector<ll> prt;queue<ll> q;
void addl(ll x,ll y,ll w){
a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;a[tot].w=w;
a[++tot].to=x;a[tot].next=ls[y];ls[y]=tot;a[tot].w=0;
}
bool bfs(ll s,ll t){
while(!q.empty())q.pop();q.push(s);
memset(dep,0,sizeof(dep));dep[s]=1;
while(!q.empty()){
ll x=q.front();q.pop();
for(ll i=ls[x];i;i=a[i].next){
ll y=a[i].to;
if(dep[y]||!a[i].w)continue;
dep[y]=dep[x]+1;
if(y==t)return 1;
q.push(y);
}
}
return 0;
}
ll dinic(ll x,ll t,ll flow){
if(x==t)return flow;
ll rest=0,k;
for(ll i=ls[x];i;i=a[i].next){
ll y=a[i].to;
if(dep[x]+1!=dep[y]||!a[i].w)continue;
rest+=(k=dinic(y,t,min(flow-rest,a[i].w)));
a[i].w-=k;a[i^1].w+=k;
if(rest==flow)return flow;
}
if(!rest)dep[x]=0;
return rest;
}
bool cmp(ll x,ll y)
{return C[x]<C[y];}
signed main()
{
scanf("%lld",&T);
while(T--){
memset(ls,0,sizeof(ls));tot=1;
scanf("%lld",&n);
for(ll i=1;i<=n;i++)scanf("%lld",&A[i]);
for(ll i=1;i<=n;i++)scanf("%lld",&B[i]);
for(ll i=1;i<=n;i++)scanf("%lld",&C[i]);
ll maxs=0,s=2*n+1,t=s+1;
for(ll i=1;i<=n;i++){
f[i]=1;p[i]=i;
for(ll j=1;j<i;j++)
if(A[i]>A[j])f[i]=max(f[i],f[j]+1);
maxs=max(maxs,f[i]);
}
for(ll i=1;i<=n;i++){
if(f[i]==1)addl(s,i,inf);
if(f[i]==maxs)addl(i+n,t,inf);
addl(i,i+n,B[i]);
for(ll j=i+1;j<=n;j++)
if(A[i]<A[j]&&f[i]+1==f[j])
addl(i+n,j,inf);
}
ll ans=0;prt.clear();
while(bfs(s,t))
ans+=dinic(s,t,inf);
printf("%lld ",ans);
sort(p+1,p+1+n,cmp);
for(ll i=1;i<=n;i++){
ll x=p[i];
if(bfs(x,x+n))continue;
while(bfs(t,x+n))dinic(t,x+n,inf);
while(bfs(x,s))dinic(x,s,inf);
prt.push_back(x);
}
printf("%lld\n",prt.size());
sort(prt.begin(),prt.end());
for(ll i=0;i<prt.size();i++)
printf("%lld ",prt[i]);
putchar('\n');
}
return 0;
}

P3308-[SDOI2014]LIS【最小割】的更多相关文章

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

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

  2. P3308 [SDOI2014]LIS(最小割+退流)

    传送门 设\(f[i]\)为以\(i\)结尾的最长上升子序列.可以考虑建这样一张图,对于所有的\(i<j,f[j]=f[i+1]\)连边\((i,j)\),\(f[i]=1\)的话连边\((S, ...

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

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

  4. 【BZOJ-3532】Lis 最小割 + 退流

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

  5. hdu3739 Anti LIS[最小割]

    长度为 n≤1000 的数列 ai,其中最长上升子序列的长度为 s.至少删去多少数使得最长上升子序列的长度小于 s. 其实这题和那个求有多少不重叠LIS是一样答案的. 先放个图. 图丑别说我. 原网络 ...

  6. 洛谷$P3308\ [SDOI2014]LIS$ 网络流

    正解:网络流 解题报告: 传送门$QwQ$ 恩先不考虑关于那个附加属性的限制,考虑这题怎么做? 首先这题从名字开始就让人忍不住联想起网络流24题里的那个最长不下降子序列?于是同样考虑预处理一个$f$呗 ...

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

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

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

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

  9. 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连边 ...

随机推荐

  1. redisson 分布式加锁

    <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring- ...

  2. freeswitch新增模块

    概述 freeswitch的架构由稳定的核心模块和大量的外围插件式模块组成.核心模块保持稳定,外围模块可以动态的加载/卸载,非常灵活方便. 外围模块通过核心提供的 Public API与核心进行通信, ...

  3. call bind apply的区别

    call() 和apply()的第一个参数相同,就是指定的对象.这个对象就是该函数的执行上下文. call()和apply()的区别就在于,两者之间的参数. call()在第一个参数之后的 后续所有参 ...

  4. 解决移动端click事件300ms延迟的问题

    方法1.部分浏览器的<meta>标签加上width=device-width就能解决. 方法2.引入fastclick.js库 <!DOCTYPE html> <html ...

  5. 🏆【JVM技术专区】「难点-核心-遗漏」TLAB内存分配+锁的碰撞(技术串烧)!

    JVM内存分配及申请过程 当使用new关键字或者其他任何方式进行创建一个类的对象时,JVM虚拟机需要为该对象分配内存空间,而对象的大小在类加载完成后已经确定了,所以分配内存只需要在Java堆中划分出一 ...

  6. 并发编程之:Lock

    大家好,我是小黑,一个在互联网苟且偷生的农民工. 在之前的文章中,为了保证在并发情况下多线程共享数据的线程安全,我们会使用synchronized关键字来修饰方法或者代码块,以及在生产者消费者模式中同 ...

  7. Linux 安装 Harbor 私有镜像仓库

    下载 最新发行:https://github.com/goharbor/harbor/releases # 下载文件 wget https://github.com/goharbor/harbor/r ...

  8. 用XPath定位Web页面元素时,如何快速验证XPath语句是否正确?

    在使用Selenium做Web UI自动化测试的过程中,XPath是一种定位页面元素的常用方式.然而,面对某些元素的XPath路径过于复杂,我们想快速验证拼凑的Xpath语句是否正确时,该怎么办呢?这 ...

  9. xxs攻击

    1 XSS是一种经常出现在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中.比如这些代码包括HTML代码和客户端脚本.攻击者利用XSS漏洞旁路掉访问控制--例如 ...

  10. noip模拟31

    \(\color{white}{\mathbb{峭壁通天,横崖无岸,惊无识之马,断无疆之虹,名之以:悬崖}}\) 一看完题就暴肝 \(t1\),胡了两个贪心,实现了一个,发现都是错的,然后奖金两个小时 ...