bzoj 3532 lis
2015-11-16 10:38
127 查看
dp求出lis的f数组,分层图建图,注意只向能转移到的连边。输出方案,如果那条边“可以”在最小割上,去掉那条边,dinic(x,S),dinic(T,x+n)退流,重新计算targan错误:忘记把lis清零了。
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<cmath> #define md #define ll long long #define inf 10000000000000LL #define eps 1e-8 #define N 5010 #define M 520000 using namespace std; struct yts { int x,t,ne; ll f;} e[2*M]; int v ,dep ,q ,f ,head ,dfn ,low ,scc ,st ,a ,path ,as ; ll b ; struct CC {int x,id;} c ; int num,s,t,S,T,dfs_cnt,scc_cnt,n,lis,top; ll ans; void put(int x,int y,ll f) { num++; e[num].x=x; e[num].t=y; e[num].f=f; e[num].ne=v[x]; v[x]=num; } void add(int x,int y,ll f) { put(x,y,f); put(y,x,0); } bool cmp(CC a,CC b) { return a.x<b.x; } bool bfs() { int h=0,w=1,x,y; dep[s]=1; q[1]=s; while (h<w) { x=q[++h]; for (int i=v[x];i;i=e[i].ne) { y=e[i].t; if (!dep[y]&&e[i].f) { dep[y]=dep[x]+1; q[++w]=y; } } } return dep[t]!=0; } ll dfs(int x,ll fl) { if (x==t) return fl; ll now=0,used=0; for (int i=head[x];i;i=e[i].ne) { int y=e[i].t; if (e[i].f&&dep[y]==dep[x]+1) { now=dfs(y,min(e[i].f,fl-used)); used+=now; e[i].f-=now; e[i^1].f+=now; if (e[i].f) head[x]=i; if (used==fl) break; } } if (used==0) dep[x]=-1; return used; } void dinic(int x,int y,ll mx) { s=x; t=y; ans=0; while (1) { memset(dep,0,sizeof(dep)); for (int i=1;i<=T;i++) head[i]=v[i]; if (bfs()) ans+=dfs(s,inf); else break; } } void ycl() { num=1; dfs_cnt=0; scc_cnt=0; top=0; lis=0; memset(f,0,sizeof(f)); memset(v,0,sizeof(v)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(scc,0,sizeof(scc)); } void dp() { for (int i=1;i<=n;i++) { for (int j=1;j<i;j++) if (a[j]<a[i]) f[i]=max(f[i],f[j]); f[i]++; lis=max(lis,f[i]); } } void build() { dp(); for (int i=1;i<=n;i++) { path[i]=num+1; add(i,i+n,b[i]); if (f[i]==1) add(S,i,inf); for (int j=1;j<i;j++) if (a[j]<a[i]&&f[i]==f[j]+1) add(j+n,i,inf); if (f[i]==lis) add(i+n,T,inf); } } void targan(int x) { dfn[x]=low[x]=++dfs_cnt; st[++top]=x; for (int i=v[x];i;i=e[i].ne) { if (!e[i].f) continue; int y=e[i].t; if (!dfn[y]) { targan(y); low[x]=min(low[x],low[y]); } else if (!scc[y]) low[x]=min(low[x],dfn[y]); } if (dfn[x]==low[x]) { scc_cnt++; int y; do { y=st[top--]; scc[y]=scc_cnt; } while (y!=x); } } void outit() { for (int i=2;i<=num;i++) printf("%d %d %lld\n",e[i].x,e[i].t,e[i].f); printf("\n"); } int main() { int tt; scanf("%d",&tt); while (tt--) { ycl(); scanf("%d",&n); S=2*n+3; T=2*n+4; for (int i=1;i<=n;i++) scanf("%d",&a[i]); for (int i=1;i<=n;i++) scanf("%lld",&b[i]); for (int i=1;i<=n;i++) { scanf("%d",&c[i].x); c[i].id=i;} sort(c+1,c+n+1,cmp); build(); ans=0; dinic(S,T,inf); ll mxflow=ans; for (int i=1;i<=T;i++) if (!scc[i]) targan(i); int w=0; for (int i=1;i<=n;i++) { int x=c[i].id,pa=path[x]; if (!e[pa].f&&scc[e[pa].x]!=scc[e[pa].t]) { as[++w]=x; e[pa].f=e[pa^1].f=0; dinic(x,S,b[x]); dinic(T,x+n,b[x]); dfs_cnt=scc_cnt=0; memset(dfn,0,sizeof(dfn)); memset(scc,0,sizeof(scc)); for (int i=1;i<=T;i++) if (!scc[i]) targan(i); } } sort(as+1,as+w+1); printf("%lld %d\n",mxflow,w); printf("%d",as[1]); for (int i=2;i<=w;i++) printf(" %d",as[i]); printf("\n"); } return 0; }
相关文章推荐
- bzoj 3130 费用流
- bzoj 1500 维修数列 bzoj 1507 editor
- bzoj 1251 序列终结者
- bzoj 4152 the camptin (dis[x][y]=min(|x.x-y.x|,|x.y-y.y|),求1,n最短路)
- bzoj 3029 守卫者的挑战
- bzoj 2118 墨墨的等式
- <android5.0>之曲线动画(Curved motion(曲线运动))
- 浅谈虚数i在电路分析中的作用
- 【数据库7】字段相关与联合结果集
- Jenkins入门系列之——02第二章 Jenkins安装与配置
- 简述类目的优缺点,如果覆盖了本类或者父类的方法 ,会出现什么问题
- [Hibernate系列—] 1. 下载与试用Hibernate(MySQL与Oracle 配置)
- Java中String转化为其他类型方法汇总
- 用R做线性回归
- 出圈问题
- Jenkins入门系列之——01第一章 Jenkins是什么?
- bzoj 4010 菜肴制作|拓扑排序|priority_queue|解题思想
- bzoj 1414 对称的正方形
- 网络流刷题列表
- bzoj 2084 反对称子串