您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: