BZOJ3532: [Sdoi2014]Lis

感谢ZYF神犇的耐心解答……

如果这题只要求最小代价……那就是一个比较明显的拆点最小割,对于所有\(j<i、a[j]<a[i]、f_i=f_j+1\)的\(i\)和\(j\)之间连一条边。

但是题目要求字典序最小,我们要用退流算法。

我们考虑从点\(i\)到\(i‘\)的一条满流边,它是最小割中的边当且仅当不能从\(i\)增广到\(i‘\)。

退流的话也不难,直接从\(T\)到\(i‘\)和\(i\)到\(S\)做两次最大流,再删掉\(i\)到\(i‘\)这条边。


  1 /**************************************************************
2 Problem: 3532
3 User: zhuohan123
4 Language: C++
5 Result: Accepted
6 Time:9472 ms
7 Memory:18660 kb
8 ****************************************************************/
9
10 #include <iostream>
11 #include <cstdio>
12 #include <cstring>
13 #include <algorithm>
14 using namespace std;
15 typedef long long LL;
16 const int maxpoint=11000,maxedge=1100000;
17 const LL inf=~0ULL>>3;
18 int head[maxpoint],nowhead[maxpoint],pointsize;
19 struct edge{int to,next;LL c;}g[maxedge];int gnum=1;
20 void addedge(int from,int to,LL c)
21 {
22 g[++gnum].to=to;g[gnum].c=c;g[gnum].next=head[from];head[from]=gnum;
23 g[++gnum].to=from;g[gnum].c=0;g[gnum].next=head[to];head[to]=gnum;
24 }
25 int dfsstart,dfsend,dis[maxpoint];
26 int q[maxpoint],ql,qr;
27 bool BFS()
28 {
29 for(int i=1;i<=pointsize;i++)nowhead[i]=head[i],dis[i]=0;
30 ql=1;qr=0;q[++qr]=dfsend;
31 while(ql<=qr)
32 for(int now=q[ql++],i=head[now];i;i=g[i].next)
33 if(g[i^1].c&&!dis[g[i].to]&&g[i].to!=dfsend)
34 dis[q[++qr]=g[i].to]=dis[now]+1;
35 return dis[dfsstart];
36 }
37 LL DFS(int po,LL delta)
38 {
39 if(po==dfsend)return delta;
40 LL nowans=0,tans;
41 for(int&i=nowhead[po];i&&delta;i=g[i].next)
42 if(g[i].c&&dis[g[i].to]+1==dis[po]&&(tans=DFS(g[i].to,min(delta,g[i].c))))
43 g[i].c-=tans,g[i^1].c+=tans,nowans+=tans,delta-=tans;
44 return nowans;
45 }
46 LL dinic(int start,int end)
47 {
48 dfsstart=start,dfsend=end;
49 LL ans=0;
50 while(BFS())ans+=DFS(start,inf);
51 return ans;
52 }
53 int n;
54 int a[1100],b[1100],f[1100];
55 struct T
56 {
57 int num,pos;
58 friend bool operator<(T A,T B){return A.num<B.num;}
59 }c[1100];
60 int oans[1100],ansnum;
61 int main(int argc, char *argv[])
62 {
63 //freopen("1.in","r",stdin);
64 //freopen("1.out","w",stdout);
65 int Ti;scanf("%d",&Ti);
66 while(Ti--)
67 {
68 memset(head,0,sizeof head);gnum=1;
69 scanf("%d",&n);
70 for(int i=1;i<=n;i++)scanf("%d",&a[i]);
71 for(int i=1;i<=n;i++)scanf("%d",&b[i]);
72 for(int i=1;i<=n;i++)scanf("%d",&c[i].num),c[i].pos=i;
73 int maxf=0;
74 for(int i=1;i<=n;i++)f[i]=1;
75 for(int i=1;i<=n;i++)
76 for(int j=1;j<i;j++)
77 if(a[j]<a[i])maxf=max(maxf,f[i]=max(f[i],f[j]+1));
78 for(int i=1;i<=n;i++)
79 {
80 addedge(2*i+1,2*i+2,b[i]);
81 if(f[i]==1)addedge(1,2*i+1,inf);
82 if(f[i]==maxf)addedge(2*i+2,2,inf);
83 for(int j=1;j<i;j++)
84 if(a[j]<a[i]&&(f[j]+1==f[i]))
85 addedge(2*j+2,2*i+1,inf);
86 }
87 pointsize=2*n+2;
88 LL ans=dinic(1,2);
89 sort(c+1,c+n+1);
90 ansnum=0;
91 for(int i=1;i<=n;i++)
92 {
93 int ne=0,po=c[i].pos;
94 for(int j=head[2*po+1];j;j=g[j].next)
95 if(g[j].to==2*po+2){ne=j;break ;}
96 if(g[ne].c==0)
97 {
98 dfsstart=2*po+1,dfsend=2*po+2;
99 if(!BFS())
100 {
101 dinic(2,2*po+2);
102 dinic(2*po+1,1);
103 g[ne^1].c=0;
104 oans[++ansnum]=po;
105 }
106 }
107 }
108 sort(oans+1,oans+ansnum+1);
109 printf("%lld %d\n",ans,ansnum);
110 for(int i=1;i<ansnum;i++)printf("%d ",oans[i]);printf("%d\n",oans[ansnum]);
111
112 }
113 return 0;
114 }

时间: 2024-11-14 19:28:25

BZOJ3532: [Sdoi2014]Lis的相关文章

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

http://www.lydsy.com/JudgeOnline/problem.php?id=3532 如果没有字典序的限制,那么DP拆点最小割即可 加上字典序的限制: 按c从小到大枚举最小割边集中的边,去掉这条边对网络的影响,继续枚举直至获得最小割边集 判断是不是最小割边集中的边: 在残量网络中边的起点和终点不连通 注:最小割边集中的边一定满流,但满流边不一定是最小割边集中的边 如下图所示,流量为1和3的两条边满流,但最小割边集为流量为4的那条边 去掉一条边对网络的影响: 边:u-->v 这

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

3532: [Sdoi2014]Lis Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 865  Solved: 311[Submit][Status][Discuss] Description 给定序列A,序列中的每一项Ai有删除代价Bi和附加属性Ci.请删除若干项,使得4的最长上升子序列长度减少至少1,且付出的代价之和最小,并输出方案.如果有多种方案,请输出将删去项的附加属性排序之后,字典序最小的一种. 这题难点在如何求一组最小字典序最小的最小

[SDOI2014]LIS

题目描述 给定序列A,序列中的每一项Ai有删除代价Bi和附加属性Ci.请删除若干项,使得4的最长上升子序列长度减少至少1,且付出的代价之和最小,并输出方案. 如果有多种方案,请输出将删去项的附加属性排序之后,字典序最小的一种. 输入输出格式 输入格式: 输入包含多组数据. 输入的第一行包含整数T,表示数据组数.接下来4*T行描述每组数据. 每组数据的第一行包含一个整数N,表示A的项数,接下来三行,每行N个整数A1..An,B1.,Bn,C1..Cn,满足1 < =Ai,Bi,Ci < =10^

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

传送门 设\(f[i]\)为以\(i\)结尾的最长上升子序列.可以考虑建这样一张图,对于所有的\(i<j,f[j]=f[i+1]\)连边\((i,j)\),\(f[i]=1\)的话连边\((S,i)\),\(f[i]=max(f[j])\)的话连边\((j,T)\),然后就是删去若干个点使\(S,T\)不连通并且代价最小,那么拆点最小割就行了 然后是字典序的问题.我们把所有的点按\(c\)排个序然后看看这个点也就是新图中的这条边是否可以在最小割里.只要判断一下残量网络中是否存在\(u\)到\(u

YCB 的暑期计划

前言 YCB现在很弱(TAT) 暑假有一个月,赶快狂补一下. 大概的计划如下: 首先前期会以数据结构为主,毕竟代码能力太弱,涉及内容:线段树分治.二进制分组.KD-Tree. 等数据结构做到没有智商的时候加入一波数论,内容为 杜教筛.min_25筛. 然后中途小清新一下,做一些 组合博弈与构造题. 接着继续练代码能力,顺便学一些神奇的暴力:启发式合并.dsu on tree . 然后图论也忘的差不多了,就回过头去学点新东西,大概会有spfa判负环.0/1分数规划.差分约束. 估计这个时候也没有什

@loj - [email&#160;protected]「SDOI2014」Lis

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定序列 A,序列中的每一项 Ai 有删除代价 Bi 和附加属性 Ci 请删除若干项,使得 A 的最长上升子序列长度减少至少 1,且付出的代价之和最小,并输出方案. 如果有多种方案,请输出将删去项的附加属性排序之后,字典序最小的一种. 输入格式 输入包含多组数据. 输入的第一行包含整数

小明系列问题――小明序列(LIS)

小明系列问题――小明序列 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 4521 Description 大家都知道小明最喜欢研究跟序列有关的问题了,可是也就因为这样,小明几乎已经玩遍各种序列问题了.可怜的小明苦苦地在各大网站上寻找着新的序列问题,可是找来找去都是自己早已研究过的序列.小明想既然找不到,那就自己来发明一个新的序列问题吧!

hdu4521 小明系列问题——小明序列(LIS变种 (线段树+单点更新解法))

链接: huangjing 题目:中文题目 思路: 这个题目如果去掉那个距离大于d的条件,那么必然是一个普通的LIS,但是加上那个条件后就变得复杂了.用dp的解法没有看懂,我用的线段树的解法...就是采用延迟更新的做法,用为距离要大于d啊,所以我们在循环到第i的时候,就对(i-d-1)这个点进行更新,因为如果在(i-d-1)这个点更新了,会对后面的造成影响,然后线段树的tree[]数组存的是以i结尾的最长lis,那么每次询问的时候就找最大的tree[]就可以了... 代码: 小明系列问题--小明

RQNOJ 201 奥运大包围:LIS + 拼链成环

题目链接:https://www.rqnoj.cn/problem/201 题意: 开始时n(n<=1000)个人手拉手围成一个圈. 后来这些人中的一些按顺序向里面出圈形成一个新圈.从而使原圈形成一个从高到低,最低与最高连接的圈. 新圈重复相同的操作,直到没有人要出圈为止. 问最少要形成多少个这样的圈. 题解: (1)拼链成环: 对于一个环,可以用两条由环拆开的链拼在一起表示. 例如:有一个环为"1,2,3,4"(1和4连在一起),则可以表示为"1,2,3,4,1,2,