[SDOI2014] LIS

49 篇文章 0 订阅
41 篇文章 0 订阅

题目描述:

qwq

题目分析:

求最小字典序最小割
如何判断一条边是否是割边是很容易的 只需要从u出发看是否能找到一条u到v的增广路,如果存在这样的一条路径 说明该边不是割边
那么我们按照C的大小来枚举每一条边 如果该边是割边 那么我们就要把它从图中删除(这样可以让一些割边不再是满流的边 这些删除的割边都是一定不与当前割边在同一割集中的割边 要让这样的边不能入选)
那么我们要怎样最快的消除这条边呢?我们使用退流算法 从T到v跑一次最大流 从u到S跑一遍最大流即可消除当前边的影响 再把当前边的容量设置为0

题目链接:

BZOJ 3532
Luogu 3308
Loj 2196

Ac 代码:

// luogu-judger-enable-o2
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
const int inf=0x7fffffff;
const int maxm=1505;
const int N=2000005;
int head[maxm],cap[N],to[N],net[N];
int cnt=1;
inline void add(int u,int v,int c){cnt++;to[cnt]=v,cap[cnt]=c,net[cnt]=head[u],head[u]=cnt;}
inline void addedge(int u,int v,int c){add(u,v,c),add(v,u,0);}
int deep[maxm];
std::queue<int> dl;
namespace Maxflow{
    inline bool BFS(int s,int t)
    {
        while(!dl.empty()) dl.pop();
        memset(deep,-1,sizeof(deep));
        dl.push(s),deep[s]=0;
        while(!dl.empty())
        {
            int now=dl.front();
            dl.pop();
            for(int i=head[now];i;i=net[i])
            if(cap[i]>0&&deep[to[i]]==-1)
             dl.push(to[i]),deep[to[i]]=deep[now]+1;
        }
        return deep[t]!=-1;
    }
    int dfs(int now,int flow,int t)
    {
        if(now==t) return flow;
        int w,used=0;
        for(int i=head[now];i;i=net[i])
        {
            int v=to[i];
            if(deep[v]==deep[now]+1&&cap[i])
            {
                w=dfs(v,std::min(cap[i],flow-used),t);
                cap[i]-=w,cap[i^1]+=w;
                used+=w;
                if(used==flow) return flow;
            }
        }
        if(!used) deep[now]=-1;
        return used;
    }
    int Dinic(int s,int t)
    {
        int maxflow=0;
        while(BFS(s,t)) maxflow+=dfs(s,inf,t);
        return maxflow; 
    }
}
int a[maxm],b[maxm],c[maxm],p[maxm];
int dp[maxm];
int ans[maxm],tot; 
int n;
inline int comp(int x,int y){return c[x]<c[y];}
void work()
{
    memset(head,0,sizeof(head));
    memset(dp,0,sizeof(dp)); 
    cnt=1,tot=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n;i++) scanf("%d",&b[i]);
    for(int i=1;i<=n;i++) scanf("%d",&c[i]),addedge(i,i+n,b[i]);
    for(int i=1;i<=n;i++) p[i]=i;
    std::sort(p+1,p+n+1,comp);
    int max=0;
    for(int i=1;i<=n;i++)
    {
        dp[i]=1;
        for(int j=1;j<i;j++)
         if(a[i]>a[j]) dp[i]=std::max(dp[i],dp[j]+1);
        max=std::max(max,dp[i]);
    }
    int s=0,t=2*n+10;
    for(int i=1;i<=n;i++) if(dp[i]==max) addedge(i+n,t,inf);
    for(int i=1;i<=n;i++) if(dp[i]==1) addedge(s,i,inf);
    for(int i=1;i<=n;i++)
    for(int j=1;j<i;j++)
     if(a[i]>a[j]&&dp[i]==dp[j]+1) addedge(j+n,i,inf);
    printf("%d ",Maxflow::Dinic(s,t));
    for(int i=1;i<=n;i++)
    {
        int x=p[i];
        s=x,t=x+n;
        if(cap[2*x]||Maxflow::BFS(s,t)) continue;
        s=x,t=0;
        Maxflow::Dinic(s,t);
        s=2*n+10,t=x+n;
        Maxflow::Dinic(s,t);
        cap[2*x]=cap[2*x+1]=0;
        ans[++tot]=x;   
    }
    std::sort(ans+1,ans+tot+1);
    printf("%d\n",tot);
    for(int i=1;i<=tot;i++)
     printf("%d ",ans[i]);
    puts("");

}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
     work();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Lis Delphi是一个创新科技公司,专注于开发和提供高质量的软件解决方案。该公司成立于20xx年,总部位于中国上海。Lis Delphi的主要产品和服务包括开发工具、编程语言、数据库管理系统以及各种定制化的软件解决方案。 Lis Delphi的开发工具主要是针对软件开发人员的,旨在提供一套强大的开发工具,帮助开发人员更高效地开发出功能强大、稳定可靠的软件。该开发工具具有友好的用户界面和丰富的功能模块,可以满足开发人员的各种需求。 与此同时,Lis Delphi还提供一种名为Delphi的编程语言。Delphi是一种基于对象的编程语言,结合了传统的编程语言和面向对象思想的特点。它易于学习和使用,并且具有高度可读性和可维护性。许多开发人员选择使用Delphi语言进行软件开发,因为它能够提供高效的开发环境和强大的功能。 此外,Lis Delphi还开发了一套数据库管理系统,用于帮助用户管理和存储大量的数据。这个数据库管理系统具有高速、可靠和安全等特点,可以有效地管理企业的数据,提高数据处理效率。 最后,Lis Delphi也提供各种定制化的软件解决方案。无论是企业内部的管理系统,还是对外提供的在线服务,Lis Delphi都能根据客户需求开发出最合适的解决方案,帮助客户实现数字化转型,提高业务效率。 总的来说,Lis Delphi是一家专注于软件开发和提供解决方案的科技公司,致力于提供高质量的开发工具、编程语言、数据库管理系统以及定制化的软件解决方案,满足客户的各种需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值