• [BZOJ3532][SDOI2014]LIS


    bzoj
    luogu

    sol

    假设不要求字典序最小,只求代价之和最小,那应该还是很好求的吧。
    先对原序列求出一个(LIS)(dp)数组,然后每个位置拆成两个点,所有(X_i)(Y_i)(B_i)的边,然后(S)(X_i(dp_i=1))(Y_i(dp_i=LIS))(T)(inf)边,再对于所有可以从(i)转移到的(j),连(Y_i)(X_j)(inf)边。
    求出上图中的最小割即可。
    现在问题转化为:要求最小割的字典序最小。
    字典序最小的话可以认为是贪心,更小的能选择选,因为选了一定会更优。
    先随便跑出一个最小割,然后按照(C_i)的大小从小到大考虑参与网络上的每一条边,如果边((X_i,Y_i))中的(X_i)(Y_i)不可达,则说明这条边可以处于割集中。
    然后就可以把这条边删掉,然后重新跑一边最大流,重复此操作就可以了。
    这样做的正确性可以保证,但是时间复杂度有问题。这里可以考虑退流,即把边((X_i,Y_i))对流量的贡献删除。
    只要跑一遍(T)(Y_i)(X_i)(S)的最大流就可以了。
    这个自己YY一下就可以理解了吧。

    对了,还有一个莫名其妙的常数技巧:

    bool bfs(int s,int t)
    {
        memset(dep,0,sizeof(dep));dep[s]=1;
        while (!Q.empty()) Q.pop();Q.push(s);
        while (!Q.empty())
        {
            int u=Q.front();Q.pop();
            for (int e=head[u];e;e=a[e].nxt)
                if (a[e].w&&!dep[a[e].to])
                {
                    dep[a[e].to]=dep[u]+1,Q.push(a[e].to);
                    if (a[e].to==t) return true;
                }
        }
        return false;
    }
    

    注意这里因为找到目标点就直接返回了所以队列非空,要先清空队列。
    然后这样写就(TLE)

    bool bfs(int s,int t)
    {
    	memset(dep,0,sizeof(dep));
    	dep[s]=1;Q.push(s);
    	while (!Q.empty())
    	{
    		int u=Q.front();Q.pop();
    		for (int e=head[u];e;e=a[e].nxt)
    			if (a[e].w&&!dep[a[e].to])
    				dep[a[e].to]=dep[u]+1,Q.push(a[e].to);
    	}
    	return dep[t];
    }
    

    code

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    using namespace std;
    int gi()
    {
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='0') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    const int N = 1500;
    const int inf = 1e9;
    struct edge{int to,nxt,w;}a[N*N];
    int T,n,A[N],B[N],C[N],head[N],cnt,f[N],dep[N],cur[N],id[N],ans[N];
    queue<int>Q;
    void link(int u,int v,int w)
    {
    	a[++cnt]=(edge){v,head[u],w};
    	head[u]=cnt;
    	a[++cnt]=(edge){u,head[v],0};
    	head[v]=cnt;
    }
    bool bfs(int s,int t)
    {
    	memset(dep,0,sizeof(dep));dep[s]=1;
    	while (!Q.empty()) Q.pop();Q.push(s);
    	while (!Q.empty())
    	{
    		int u=Q.front();Q.pop();
    		for (int e=head[u];e;e=a[e].nxt)
    			if (a[e].w&&!dep[a[e].to])
    			{
    				dep[a[e].to]=dep[u]+1,Q.push(a[e].to);
    				if (a[e].to==t) return true;
    			}
    	}
    	return false;
    }
    int dfs(int u,int f,int t)
    {
    	if (u==t) return f;
    	for (int &e=cur[u];e;e=a[e].nxt)
    		if (a[e].w&&dep[a[e].to]==dep[u]+1)
    		{
    			int tmp=dfs(a[e].to,min(a[e].w,f),t);
    			if (tmp) {a[e].w-=tmp;a[e^1].w+=tmp;return tmp;}
    		}
    	return 0;
    }
    int Dinic(int s,int t)
    {
    	int res=0;
    	while (bfs(s,t))
    	{
    		for (int i=1;i<=2*n+2;++i) cur[i]=head[i];
    		while (int tmp=dfs(s,inf,t)) res+=tmp;
    	}
    	return res;
    }
    bool cmp(int i,int j){return C[i]<C[j];}
    int main()
    {
    	T=gi();
    	while (T--)
    	{
    		n=gi();memset(head,0,sizeof(head));cnt=1;
    		int s=2*n+1,t=s+1,maxl=0,len=0;
    		for (int i=1;i<=n;++i) A[i]=gi();
    		for (int i=1;i<=n;++i) B[i]=gi();
    		for (int i=1;i<=n;++i) C[i]=gi();
    		for (int i=1;i<=n;++i)
    		{
    			f[i]=1;
    			for (int j=1;j<i;++j)
    				if (A[j]<A[i]) f[i]=max(f[i],f[j]+1);
    			maxl=max(maxl,f[i]);
    		}
    		for (int i=1;i<=n;++i) link(i,i+n,B[i]);
    		for (int i=1;i<=n;++i)
    		{
    			if (f[i]==1) link(s,i,inf);
    			if (f[i]==maxl) link(i+n,t,inf);
    		}
    		for (int i=1;i<n;++i)
    			for (int j=i+1;j<=n;++j)
    				if (A[i]<A[j]&&f[i]+1==f[j]) link(i+n,j,inf);
    		printf("%d ",Dinic(s,t));
    		for (int i=1;i<=n;++i) id[i]=i;
    		sort(id+1,id+n+1,cmp);
    		for (int i=1;i<=n;++i)
    			if (!bfs(id[i],id[i]+n))
    			{
    				ans[++len]=id[i];
    				Dinic(t,id[i]+n);Dinic(id[i],s);
    				a[id[i]<<1].w=a[id[i]<<1|1].w=0;
    			}
    		sort(ans+1,ans+len+1);
    		printf("%d
    ",len);
    		for (int i=1;i<=len;++i) printf("%d%c",ans[i],i==len?'
    ':' ');
    	}
    	return 0;
    }
    
  • 相关阅读:
    python进阶-lambda和列表生成器
    【pandas】条件查询 分组标记
    【Python】生成html文档-使用dominate
    Python对列表内部的字典进行排序 --lambda,sort
    【python3】通过hashlib 和base64 对字符串进行加密
    【Pandas】统计某个值的出现次数
    git 创建分支,切换分支,merge操作
    如何将excel单元格中一部分数据提取到另一单元格?
    整型数的溢出解决办法
    CentOS6.9安装SonarQube7.6
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8613334.html
Copyright © 2020-2023  润新知