题目链接


最多不相交路径

这种问题变化比较多,但都能表示成以下形式:

已知一些路径,每个节点只能属于一条路径,求能选择多少条路径使它们不相交.
主要的方法是拆点,将一个点拆成两个,然后连边,容量表示该点最多经过次数



解题思路:

  • 对于第一问:我们直接暴力dp[i]表示以第i个数结尾的最长不下降子序列的个数就可以求出sdp[i]表示以第i个数结尾的最长不下降子序列的个数就可以求出sdp[i]表示以第i个数结尾的最长不下降子序列的个数就可以求出s
  • 对于第二问:目的是求出sss这种路径有多少条,那么就是典型的最大路径不相交数,因为每个点只能在一个序列里面,那么我们就可以先拆点!!
  • 把x−>[x,x+n](n是数的个数)x是和源点相连,x+n是和汇点相连x->[x,x+n](n是数的个数)x是和源点相连,x+n是和汇点相连x−>[x,x+n](n是数的个数)x是和源点相连,x+n是和汇点相连,我们为了求出有多少条那么我们就要保证连向汇点的一定是dp[i]为s的点!dp[i]为s的点!dp[i]为s的点!,而且图上连上汇点的点应该dp[i]为1的点dp[i]为1的点dp[i]为1的点
  • 如果dp[i]=dp[j]+1(j<i)dp[i]=dp[j]+1(j<i)dp[i]=dp[j]+1(j<i)那么从j+n向i连边流量为1从j+n向i连边流量为1从j+n向i连边流量为1
  • 然后i向i+n连流量为1的边i向i+n连流量为1的边i向i+n连流量为1的边
  • 跑最大流的结果就是结果,对于第三问只是我们把111和nnn的所有流量变成INFINFINF就好

代码:

#include <bits/stdc++.h>
#define mid ((l + r) >> 1)
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define log2(a) log(a)/log(2)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define LLF 0x3f3f3f3f3f3f3f3f
#define f first
#define s second
#define endl '\n'
using namespace std;
const int N = 2e6 + 10, mod = 1e9 + 9;
const int maxn = 500010;
const long double eps = 1e-5;
const int EPS = 500 * 500;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef pair<double,double> PDD;
template<typename T> void read(T &x) {x = 0;char ch = getchar();ll f = 1;while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T, typename... Args> void read(T &first, Args& ... args)  {read(first);read(args...);
}
struct node {int to, next, len;
}e[maxn];
int head[maxn], cnt;
int n, m, s, t;
inline void add(int from, int to, int len) {e[cnt] = {to,head[from],len};head[from] = cnt ++;
}int dp[maxn];
int arr[maxn], num;
int maxs = -1;int d[maxn],cur[maxn];
int pre[maxn], flow[maxn];bool bfs() {ms(d,0);queue<int> q;q.push(s); d[s] = 1;while(!q.empty()) {int u = q.front(); q.pop();for(int i = head[u]; ~i; i = e[i].next) {int v = e[i].to;if(d[v] || e[i].len <= 0) continue;q.push(v);d[v] = d[u] + 1;}}      for(int i = 0; i <= n; ++ i) cur[i] = head[i];return d[t] != 0;
}int dfs(int u, int flow) {if(u == t) return flow;for(int &i = cur[u]; ~i; i = e[i].next) {int v = e[i].to;if(d[u] + 1 != d[v] || e[i].len <= 0) continue;int delta = dfs(v,min(flow,e[i].len));if(delta <= 0) continue;e[i].len -= delta;e[i^1].len += delta;return delta;}return 0;
}int get_maxflow() {int maxFlow = 0, delta;while(bfs())//bfs进行构建最短路网络while(delta = dfs(s,INF))maxFlow += delta;cout << maxFlow << "\n";if(maxs == 1) {cout << maxFlow <<"\n";exit(0);}return maxFlow;
}inline void slove_1() {for(int i = 1; i <= num; ++ i) dp[i] = 1;for(int i = 2; i <= num; ++ i)for(int j = 1; j < i; ++ j)if(arr[i] >= arr[j])dp[i] = max(dp[i],dp[j]+1);for(int i = 1; i <= num; ++ i) maxs = max(maxs,dp[i]);cout << maxs << endl;
}inline void build(int x) {ms(head,-1), cnt = 0;for(int i = 1; i <= num; ++ i) {int flow = 1;if(i == 1 || i == num) flow = x;if(dp[i] == 1) add(s,i,flow), add(i,s,0);if(dp[i] == maxs)add(i+num,t,flow), add(t,i+num,0);}for(int i = 1; i <= num; ++ i) {int flow = 1;if(i == 1 || i == num) flow = x;add(i,i+num,flow), add(i+num,i,0);}for(int i = 1; i <= num; ++ i) for(int j = 1; j < i; ++ j) if(arr[i] >= arr[j] && dp[i] == dp[j] + 1) {add(j+num,i,1);add(i,j+num,0);         }}int main() {cin >> num;s = 0, t = num << 1|1;n = t;for(int i = 1; i <= num; ++ i) cin >> arr[i];slove_1();build(1);get_maxflow();build(INF);get_maxflow();return 0;
}

最大流 ---- 最大不相交路径数 ---- P2766 最长不下降子序列问题(网络流24题)相关推荐

  1. P2766 最长不下降子序列问题(网络流)

    P2766 最长不下降子序列问题 求解LIS长度k 求解长度为k的不下降子序列个数,并且一个数只能使用一次 求解长度为k的不下降子序列个数,第一个数和第n个数可以使用任意次 首先利用dp可以求解出以每 ...

  2. 洛谷 - P2766 最长不下降子序列问题(最大流+动态规划+思维建边)

    题目链接:点击查看 题目大意:给出一个由n个数组成的序列,有三个子问题: 求出当前数列的最长不下降子序列的长度len 如果每个数最多只能使用一次,问最多可以组成多少个长度为len的最长不下降子序列 如 ...

  3. 734. [网络流24题] 方格取数问题 二分图点权最大独立集/最小割/最大流

    «问题描述: 在一个有m*n 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任 意2 个数所在方格没有公共边,且取出的数的总和最大.试设计一个满足要求的取数算法. «编程任务: 对于给定 ...

  4. 【网络流24题】魔术球问题(最大流)

    [网络流24题]魔术球问题(最大流) 题面 Cogs 题解 是不是像极了最小路径覆盖? 因此,我们枚举放到哪一个球(也可以二分) 然后类似于最小路径覆盖的连边 因为一根柱子对应一个路径的覆盖 所以,提 ...

  5. 【网络流24题】餐巾计划问题(最小费用最大流)

    [网络流24题]餐巾计划问题(最小费用最大流) 题面 COGS 洛谷上的数据范围更大,而且要开longlong 题解 餐巾的来源分为两种: ①新买的 ②旧的拿去洗 所以,两种情况分别建图 先考虑第一种 ...

  6. 【P2766】 最长不下降子序列问题

    题目描述 «问题描述: 给定正整数序列x1,...,xn . (1)计算其最长不下降子序列的长度s. (2)计算从给定的序列中最多可取出多少个长度为s的不下降子序列. (3)如果允许在取出的序列中多次 ...

  7. 【网络流24题】星际转移问题(最大流)

    [网络流24题]星际转移问题(最大流) 题面 Cogs 题解 因为天数是未知的,所以我们要想办法处理天数 可以选择二分或者依次累加天数 因为数据范围较小,使用二分可能反而复杂度会增高 所以使用不断累加 ...

  8. loj #6004. 「网络流 24 题」圆桌聚餐(最大流)

    #6004. 「网络流 24 题」圆桌聚餐 内存限制:256 MiB时间限制:5000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数 ...

  9. 【网络流24题】圆桌聚餐(最大流)

    [网络流24题]圆桌聚餐(最大流) 题面 Cogs 题解 这道题很简单 首先每个单位的人数限制 直接从源点向单位连边,容量为人数 同样的, 每个桌子向汇点连边,容量为可以坐的人数 因为每个桌子只能够做 ...

最新文章

  1. python使用matplotlib, seaborn画图时候的数据加载
  2. 2020年, video captioning论文汇总
  3. LeetCode 70. Climbing Stairs
  4. JDK源码解析之java.util.ListIterator
  5. JavaScript 获得当前日期+时间
  6. ShardingSphere(一)ShardingSphere简单介绍及相关概念
  7. linux下 环境搭建教程,Linux环境下搭建pNFS使用环境教程
  8. MySQL基础 — 常用命令
  9. InfoGAN详细介绍及特征解耦图像生成
  10. SECS/GEM实现(一)半导体通讯协议软件,C、C++使用介绍
  11. 同花顺手机显示切换服务器,同花顺怎么开多个副屏,同花顺一机多屏显示设置...
  12. 如何运用python做一个有音乐的二维码_怎样制作一个背景音乐和与文字一起的二维码?...
  13. 软件测试-黑盒测试方法(二)---正交实验法、场景图、错误推测法
  14. 手机与电脑局域网内数据互通
  15. 常见的qq在线客服代码
  16. 心跳机制 heartbeat
  17. StringUtils 工具
  18. Quartus ii 与 Verilog入门教程(1)——Verilog实现8位计数器
  19. Java多线程面试题总结(常见多线程面试题)
  20. 刷脸支付助力互联网产业时代全面到来

热门文章

  1. call ret指令的总结
  2. MATLAB_no.1:入门作业_histeq():_imhist()_(男孩的三个图,以及文字描述)
  3. 干货 | 抖音漫画效果解密
  4. ∇SLAM:自动可微分SLAM
  5. 树莓派安装docker
  6. 通讯波形记录——I2S、I2C、Uart、SPI
  7. 对于SD-WAN安全的5个误区
  8. vue2.0 + vux (五)api接口封装 及 首页 轮播图制作
  9. git for c#, clone方法
  10. 这些HTML、CSS知识点,面试和平时开发都需要 No10-No11