bzoj 3532 lis

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[N],dep[N],q[N],f[N],head[N],dfn[N],low[N],scc[N],st[N],a[N],path[N],as[N];
ll b[N];
struct CC {int x,id;} c[N];
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 3532 lis)