【BZOJ-3532】Lis 最小割 + 退流
3532: [Sdoi2014]Lis
Time Limit: 10 Sec Memory Limit: 512 MB
Submit: 704 Solved: 264
[Submit][Status][Discuss]
Description
给定序列A,序列中的每一项Ai有删除代价Bi和附加属性Ci。请删除若干项,使得4的最长上升子序列长度减少至少1,且付出的代价之和最小,并输出方案。
如果有多种方案,请输出将删去项的附加属性排序之后,字典序最小的一种。
Input
输入包含多组数据。
输入的第一行包含整数T,表示数据组数。接下来4*T行描述每组数据。
每组数据的第一行包含一个整数N,表示A的项数,接下来三行,每行N个整数A1..An,B1.,Bn,C1..Cn,满足1 < =Ai,Bi,Ci < =10^9,且Ci两两不同。
Output
对每组数据,输出两行。第一行包含两个整数S,M,依次表示删去项的代价和与数量;接下来一行M个整数,表示删去项在4中的的位置,按升序输出。
Sample Input
6
3 4 4 2 2 3
2 1 1 1 1 2
6 5 4 3 2 1
Sample Output
2 3 6
解释:删去(A2,43,A6),(A1,A6),(A2,43,44,A5)等都是合法的方案,但{A2,43,A6)对应的C值的字典序最小。
HINT
1 < =N < =700 T < =5
Source
Solution
最小割的模型还是很显然的,先dp一边,然后转移之间连边,源点到初始状态,最终状态到汇点,拆点限制流量,最小割即删去的代价。
然后考虑字典序最小的割,可以通过按字典序枚举每条限流边,如果这条边满流且无法再流过去,则这条割边可选,然后消除它的影响,继续处理。
消除影响可以利用退流的思想,其实就是将这条边<u,v>正反置0,然后跑一遍T->v,一遍u->S即可。
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std; inline int read()
{
int x=0,f=1; char ch=getchar();
while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
} #define MAXN 5010
int N,cas,a[MAXN],b[MAXN],c[MAXN]; struct EdgeNode{
int next,to,cap;
}edge[2000100];
int head[MAXN],cnt=1;
inline void AddEdge(int u,int v,int w) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].cap=w;}
inline void InsertEdge(int u,int v,int w) {AddEdge(u,v,w); AddEdge(v,u,0);} int h[MAXN],cur[MAXN],S,T;
queue<int>q;
inline bool bfs(int s,int t)
{
for (int i=S; i<=T; i++) h[i]=-1;
q.push(s); h[s]=0;
while (!q.empty()) {
int now=q.front(); q.pop();
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].cap && h[edge[i].to]==-1)
h[edge[i].to]=h[now]+1,q.push(edge[i].to);
}
return h[t]!=-1;
} inline int dfs(int now,int low,int s,int t)
{
if (now==t) return low;
int w,used=0;
for (int i=cur[now]; i; i=edge[i].next)
if (edge[i].cap && h[edge[i].to]==h[now]+1) {
int w=dfs(edge[i].to,min(low-used,edge[i].cap),s,t);
edge[i].cap-=w; edge[i^1].cap+=w; used+=w;
if (used==low) return used;
if (edge[i].cap) cur[now]=i;
}
if (!used) h[now]=-1;
return used;
} #define INF 0x7fffffff
inline int Dinic(int s,int t)
{
int re=0;
while (bfs(s,t)) {
for (int i=S; i<=T; i++) cur[i]=head[i];
re+=dfs(s,INF,s,t);
}
return re;
} #define Pa pair<int,int>
#define MP make_pair
#define Id first
#define ps second inline bool cmp(Pa x,Pa y) {return c[x.Id]<c[y.Id];} int stack[MAXN],top=0;
int main()
{
cas=read();
while (cas--) {
cnt=1;
memset(head,0,sizeof(head)); N=read();
for (int i=1; i<=N; i++) a[i]=read();
for (int i=1; i<=N; i++) b[i]=read();
for (int i=1; i<=N; i++) c[i]=read(); static int f[MAXN]; for (int i=1; i<=N; i++) f[i]=1; for (int i=1; i<=N; i++)
for (int j=0; j<i; j++)
if (a[i]>a[j]) f[i]=max(f[i],f[j]+1); int mx=0;
for (int i=1; i<=N; i++) mx=max(mx,f[i]); S=0,T=2*N+1; static Pa id[MAXN]; for (int i=1; i<=N; i++) {
if (f[i]==1) InsertEdge(S,i,INF);
if (f[i]==mx) InsertEdge(i+N,T,INF);
InsertEdge(i,i+N,b[i]); id[i]=MP(i,cnt);
for (int j=1; j<i; j++)
if (f[i]-1==f[j] && a[i]>a[j]) InsertEdge(j+N,i,INF);
} int ans=Dinic(S,T); stable_sort(id+1,id+N+1,cmp); top=0;
for (int i=1; i<=N; i++) {
int e1=id[i].ps^1,e2=id[i].ps,p1=id[i].Id,p2=p1+N;
if (!edge[e1].cap && !bfs(p1,p2)) {
Dinic(p1,S); Dinic(T,p2);
edge[e1].cap=edge[e2].cap=0;
stack[++top]=id[i].Id;
}
} stable_sort(stack+1,stack+top+1); printf("%d %d\n",ans,top);
for (int i=1; i<top; i++) printf("%d ",stack[i]); printf("%d\n",stack[top]); }
return 0;
}
【BZOJ-3532】Lis 最小割 + 退流的更多相关文章
- P3308 [SDOI2014]LIS(最小割+退流)
传送门 设\(f[i]\)为以\(i\)结尾的最长上升子序列.可以考虑建这样一张图,对于所有的\(i<j,f[j]=f[i+1]\)连边\((i,j)\),\(f[i]=1\)的话连边\((S, ...
- hdu4289 最小割最大流 (拆点最大流)
最小割最大流定理:(参考刘汝佳p369)增广路算法结束时,令已标号结点(a[u]>0的结点)集合为S,其他结点集合为T=V-S,则(S,T)是图的s-t最小割. Problem Descript ...
- 【BZOJ-1797】Mincut 最小割 最大流 + Tarjan + 缩点
1797: [Ahoi2009]Mincut 最小割 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1685 Solved: 724[Submit] ...
- BZOJ-1001 狼抓兔子 (最小割-最大流)平面图转对偶图+SPFA
1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec Memory Limit: 162 MB Submit: 14686 Solved: 3513 [Submit][ ...
- hdu1569 方格取数(2) 最大点权独立集=总权和-最小点权覆盖集 (最小点权覆盖集=最小割=最大流)
/** 转自:http://blog.csdn.net/u011498819/article/details/20772147 题目:hdu1569 方格取数(2) 链接:https://vjudge ...
- BZOJ1001:狼抓兔子(最小割最大流+vector模板)
1001: [BeiJing2006]狼抓兔子 Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨, ...
- HDU1565 方格取数(1) —— 状压DP or 插头DP(轮廓线更新) or 二分图点带权最大独立集(最小割最大流)
题目链接:https://vjudge.net/problem/HDU-1565 方格取数(1) Time Limit: 10000/5000 MS (Java/Others) Memory L ...
- 最小割最大流定理&残量网络的性质
最小割最大流定理的内容: 对于一个网络流图 $G=(V,E)$,其中有源点和汇点,那么下面三个条件是等价的: 流$f$是图$G$的最大流 残量网络$G_f$不存在增广路 对于$G$的某一个割$(S,T ...
- Destroying The Graph 最小点权集--最小割--最大流
Destroying The Graph 构图思路: 1.将所有顶点v拆成两个点, v1,v2 2.源点S与v1连边,容量为 W- 3.v2与汇点连边,容量为 W+ 4.对图中原边( a, b ), ...
随机推荐
- SQL语句(八)按条件查询
SELECT * FROM student SELECT sclass, snumb, sname FROM student --物理班有哪些同学 --年龄小于20岁的有哪些同学? --定价在30元以 ...
- 【51Nod】1519 拆方块 贪心+递推
[题目]1519 拆方块 [题意]给定n个正整数,\(A_i\)表示第i堆叠了\(A_i\)个石子.每轮操作将至少有一面裸露的石子消除,问几轮所有石子均被消除.\(n \leq 10^5\). [算法 ...
- 20155306 2016-2017-2 《Java程序设计》第5周学习总结
20155306 2016-2017-2 <Java程序设计>第5周学习总结 教材学习内容总结 第八章 异常处理 8.1 语法与继承架构 Java中所有错误都会被打包为对象,运用try.c ...
- scala笔记之惰性赋值(lazy)
一.lazy关键字简介 lazy是scala中用来实现惰性赋值的关键字,被lazy修饰的变量初始化的时机是在第一次使用此变量的时候才会赋值,并且仅在第一次调用时计算值,即值只会被计算一次,赋值一次,再 ...
- casperjs 知乎登陆
phantom.casperTest = true; phantom.outputEncoding="utf-8"; var fs = require('fs'); var cas ...
- Winform/WPF Clipboard之剪切复制粘贴
Winform // <summary> /// 复制或剪切文件至剪贴板(方法) /// </summary> /// <param name="files&q ...
- python文件操作及格式化输出
1 文件与IO 1.1读写文本数据 读写各种不同的文本数据,如ASCII,UTF-8,UTF-9编码等. 使用带有rt模式的open()函数读取文本文件. 例如: with open('db', 'r ...
- 测试开发之前端——No3.HTML5中的标准属性
HTML5的标准属性 属性 值 描述 accesskey character 规定访问元素的键盘快捷键 class classname 规定元素的类名(用于规定样式表中的类). contentedit ...
- SqlServer 递归查询树
递归关于进行树形结构的查询: 一:简单的树形结构代码. -- with一个临时表(括号中是你要查询的列名) with temp(ID,PID,Name,curLevel) as ( --1:初始查询( ...
- IDEA中Ctrl+Shift+F快捷键无效的解决方式
某天突然发现idea非常重要的快捷键ctrl+shift+F无效了,网上搜了很多都说是qq快捷键冲突,但是找了下qq快捷键却没有解决,现在给大家一个解决快捷键冲突的思路: 1.查看QQ快捷键--> ...