【PowerOJ1741&网络流24题】最长递增子序列问题(最大流)
题意:
思路:
【问题分析】
第一问时LIS,动态规划求解,第二问和第三问用网络最大流解决。
【建模方法】
首先动态规划求出F[i],表示以第i位为开头的最长上升序列的长度,求出最长上升序列长度K。
1、把序列每位i拆成两个点<i.a>和<i.b>,从<i.a>到<i.b>连接一条容量为1的有向边。
2、建立附加源S和汇T,如果序列第i位有F[i]=K,从S到<i.a>连接一条容量为1的有向边。
3、如果F[i]=1,从<i.b>到T连接一条容量为1的有向边。
4、如果j>i且A[i] < A[j]且F[j]+1=F[i],从<i.b>到<j.a>连接一条容量为1的有向边。
求网络最大流,就是第二问的结果。把边(<1.a>,<1.b>)(<N.a>,<N.b>)(S,<1.a>)(<N.b>,T)这四条边的容量修改为无穷大,再求一次网络最大流,就是第三问结果。
【建模分析】
上述建模方法是应用了一种分层图的思想,把图每个顶点i按照F[i]的不同分为了若干层,这样图中从S出发到T的任何一条路径都是一个满足条件的最长上升子序列。由于序列中每个点要不可重复地取出,
需要把每个点拆分成两个点。单位网络的最大流就是增广路的条数,所以最大流量就是第二问结果。第三问特殊地要求x1和xn可以重复使用,只需取消这两个点相关边的流量限制,求网络最大流即可。
实质上也只有两层,不如叫裂点
单位网络的最大流就是增广路的条数 这个性质需要记住
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int,int> PII;
typedef pair<ll,ll> Pll;
typedef vector<int> VI;
typedef vector<PII> VII;
typedef pair<ll,ll>P;
#define N 100010
#define M 1000000
#define INF 1e9
#define fi first
#define se second
#define MP make_pair
#define pb push_back
#define pi acos(-1)
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
#define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
#define lowbit(x) x&(-x)
#define Rand (rand()*(1<<16)+rand())
#define id(x) ((x)<=B?(x):m-n/(x)+1)
#define ls p<<1
#define rs p<<1|1 const ll MOD=1e9+,inv2=(MOD+)/;
double eps=1e-;
int dx[]={-,,,};
int dy[]={,,-,}; int head[N],vet[N],len[N],nxt[N],dp[N],a[N],dis[N],num[N][],s,S,T,K,n,tot; int read()
{
int v=,f=;
char c=getchar();
while(c<||<c) {if(c=='-') f=-; c=getchar();}
while(<=c&&c<=) v=(v<<)+v+v+c-,c=getchar();
return v*f;
} void add(int a,int b,int c)
{
nxt[++tot]=head[a];
vet[tot]=b;
len[tot]=c;
head[a]=tot; nxt[++tot]=head[b];
vet[tot]=a;
len[tot]=;
head[b]=tot;
} bool bfs()
{
queue<int>q;
rep(i,,s) dis[i]=-;
q.push(S),dis[S]=;
while(!q.empty())
{
int u=q.front();
q.pop();
int e=head[u];
while(e)
{
int v=vet[e];
if(len[e]&&dis[v]==-)
{
dis[v]=dis[u]+;
q.push(v);
}
e=nxt[e];
}
}
return dis[T]!=-;
} int dfs(int u,int aug)
{
if(u==T) return aug;
int e=head[u],val=,flow=;
while(e)
{
int v=vet[e];
if(len[e]&&dis[v]==dis[u]+)
{
int t=dfs(v,min(len[e],aug));
if(!t)
{
e=nxt[e];
continue;
}
flow+=t;
aug-=t;
len[e]-=t;
len[e^]+=t;
if(!aug) break;
}
e=nxt[e];
}
if(!flow) dis[u]=-;
return flow;
} int maxflow()
{
int res=;
while(bfs()) res+=dfs(S,INF);
return res;
} void solve1()
{
s=;
rep(i,,n)
rep(j,,) num[i][j]=++s;
S=++s;
T=++s;
rep(i,,s) head[i]=;
tot=;
rep(i,,n) add(num[i][],num[i][],);
rep(i,,n)
if(dp[i]==) add(S,num[i][],);
rep(i,,n)
if(dp[i]==K) add(num[i][],T,);
rep(i,,n)
rep(j,i+,n)
if(a[j]>a[i]&&dp[j]==dp[i]+) add(num[i][],num[j][],);
int ans=maxflow();
printf("%d\n",ans);
} void solve2()
{
rep(i,,s) head[i]=;
tot=;
add(num[][],num[][],INF);
add(num[n][],num[n][],INF);
rep(i,,n-) add(num[i][],num[i][],);
rep(i,,n)
if(dp[i]==)
{
if(i==||i==n) add(S,num[i][],INF);
else add(S,num[i][],);
} rep(i,,n)
if(dp[i]==K)
{
if(i==||i==n) add(num[i][],T,INF);
else add(num[i][],T,);
} rep(i,,n)
rep(j,i+,n)
if(a[j]>a[i]&&dp[j]==dp[i]+) add(num[i][],num[j][],);
int ans=maxflow();
if(ans>INF) ans=n;
printf("%d\n",ans);
} int main()
{
//freopen("1.in","r",stdin);
n=read();
rep(i,,n) a[i]=read();
rep(i,,n)
{
dp[i]=;
rep(j,,i-)
if(a[j]<a[i]) dp[i]=max(dp[i],dp[j]+);
}
K=;
rep(i,,n) K=max(K,dp[i]);
printf("%d\n",K);
solve1();
solve2();
return ;
}
【PowerOJ1741&网络流24题】最长递增子序列问题(最大流)的更多相关文章
- COGS731 [网络流24题] 最长递增子序列(最大流)
给定正整数序列x1,..., xn (n<=500).(1)计算其最长递增子序列的长度s.(2)计算从给定的序列中最多可取出多少个长度为s的递增子序列.(3)如果允许在取出的序列中多次使用x1和 ...
- Cogs 731. [网络流24题] 最长递增子序列(最大流)
[网络流24题] 最长递增子序列 ★★★☆ 输入文件:alis.in 输出文件:alis.out 简单对比 时间限制:1 s 内存限制:128 MB «问题描述: 给定正整数序列x1,-, xn. ( ...
- loj6005 [网络流24题]最长递增子序列
题意:给你一个序列,求不严格上升lcs长度/最多有几个没有重复元素的lcs/如果x1和xn可以多次出现,求最多有几个lcs?n<=500. 标程: #include<cstdio> ...
- COGS743. [网络流24题] 最长k可重区间集
743. [网络流24题] 最长k可重区间集 ★★★ 输入文件:interv.in 输出文件:interv.out 简单对比时间限制:1 s 内存限制:128 MB «问题描述: «编 ...
- [网络流24题]最长k可重区间集[题解]
最长 \(k\) 可重区间集 题目大意 给定实心直线 \(L\) 上 \(n\) 个开区间组成的集合 \(I\) ,和一个正整数 \(k\) ,试设计一个算法,从开区间集合 \(I\) 中选取开区间集 ...
- LibreOJ #6013. 「网络流 24 题」负载平衡 最小费用最大流 供应平衡问题
#6013. 「网络流 24 题」负载平衡 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 ...
- LibreOJ #6008. 「网络流 24 题」餐巾计划 最小费用最大流 建图
#6008. 「网络流 24 题」餐巾计划 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 ...
- [网络流24题] 最长K可重区间集问题
题目链接:戳我 当时刷24题的时候偷了懒,没有写完,结果落下这道题没有写qwq结果今天考试T3中就有一部分要用到这个思想,蒟蒻我硬是没有想到网络流呜呜呜 最大费用流. 就是我们考虑将问题转化一下,转化 ...
- P2766 [网络流24题]最长不下降子序列问题
ha~ «问题描述: 给定正整数序列$x_1,...,x_n$ .$n<=500$ 求(1)计算其最长不下降子序列的长度$s$. (2)计算从给定的序列中最多可取出多少个长度为$s$的不下降子序 ...
随机推荐
- Python基础语法之字典
1 字典基础 1.1 字典是无序的对象的集合,通过键来存取,字典的键只能是不可变类型. 1.3 字典的长度可变,异构,任意嵌套. 1.2 python中不可变数据类型包括:数值类型,字符串和元组. 2 ...
- Java第一周总结
通过两周的Java学习最深刻的体会就是Java好像要比C要简单一些. 然后这两周我学习到了很多东西,李老师第一次上课就给我们介绍了Java的发展历程,同时还有Java工具jdk的发展历程. Java语 ...
- 第8周课程总结&实验报告6
实验六 Java异常 实验目的 理解异常的基本概念: 掌握异常处理方法及熟悉常见异常的捕获方法. 实验要求 练习捕获异常.声明异常.抛出异常的方法.熟悉try和catch子句的使用. 掌握自定义异常类 ...
- 2019 计蒜之道 初赛 第一场 商汤的AI伴游小精灵
https://nanti.jisuanke.com/t/39260 根据题意我们可以知道 这是一个树 我们只需要找到出度最大的两个点就好了 如果包含根节点的话要-- 两个点相邻的话也要-- 数据很 ...
- Eclipse使用jdbc连接MySql数据库报:java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)
在使用eclipse连接mysql数据库时报异常: java.sql.SQLException: Access denied for user 'root'@'localhost' (using pa ...
- Spark-Core RDD中函数(变量)传递
我们进行 Spark 进行编程的时候,初始化工作是在driver端完成的,而实际的运行程序是在executor端进行,所以就涉及到了进程间的通讯,数据是需要序列化的 1.传递函数 import org ...
- 通过metaclass实现精简的ORM框架
摘抄于<python-3-廖雪峰> 使用ORM框架 class User(Model): #定义类的属性到列的映射: id = IntegerFiled('id') name = Stri ...
- Linear Discriminant Analysis
Suppose that we model each class density as multivariate Gaussian, in practice we do not know the pa ...
- HNUSTOJ 1601:名字缩写
1601: 名字缩写 时间限制: 1 Sec 内存限制: 128 MB 提交: 288 解决: 80 [提交][状态][讨论版] 题目描述 Noname老师有一个班的学生名字要写,但是他太懒了,想 ...
- sublime3故障收集emmet无法安装pyv8
本文主要介绍Sublime Text如何开启debug模式,分析使用过程中一些常见错误情形的解决方法.情形一:Package Control:There are no packages availab ...