[codevs1906]最长递增子序列(dp+dinic)
来源:互联网 发布:js皮肤哪个好 编辑:程序博客网 时间:2024/06/15 11:20
题目:
我是超链接
题解:
拆点
把一个点拆成两个点来保证每个点用的次数。
关系的转移
dp之后发现必须满足i在j之前,i的值小于等于j的值并且dp出来的长度i+1=j的时候才能从i向j连边。
连向源点、汇点的边注意一下,并且可以当做起点和当做终点的点的边的容量注意一下,可以控制使用的次数。
代码:
#include <cstdio>#include <queue>#include <cstring>#include <iostream>#define INF 300000#define N 300000using namespace std;int f[N+5],next[N*2+5],point[N*2+5],v[N*2+5],remind[N*2+5],cur[N*2+5],tot=-1,deep[N*2+5],a[N*2+5],make[N*2+5];int b[N+5];bool c[N*2+5];void addline(int x,int y,int bb){++tot; next[tot]=point[x]; point[x]=tot; v[tot]=y; remind[tot]=bb;++tot; next[tot]=point[y]; point[y]=tot; v[tot]=x; remind[tot]=0;}bool bfs(int s,int t){queue <int> q;for (int i=s;i<=t;i++) cur[i]=point[i];memset(deep,0x7f,sizeof(deep)); deep[s]=0; q.push(s); while (!q.empty()) { int x=q.front(); q.pop(); for (int i=point[x];i!=-1;i=next[i]) if (remind[i] && deep[v[i]]>INF) q.push(v[i]),deep[v[i]]=deep[x]+1;} return deep[t]<INF;}int dfs(int now,int t,int limit){if (now==t || !limit) return limit;int flow=0,f;for (int i=cur[now];i!=-1;i=next[i]){cur[now]=i;if (deep[v[i]]==deep[now]+1 && (f=dfs(v[i],t,min(limit,remind[i])))){flow+=f;limit-=f;remind[i]-=f;remind[i^1]+=f;make[now]=v[i];if (!limit) break;}}return flow;}int dinic(int s,int t){int ans=0;while (bfs(s,t)) ans+=dfs(s,t,INF);return ans;}int main(){int i,n,j;memset(point,-1,sizeof(point));memset(next,-1,sizeof(next)); memset(b,0,sizeof(b));scanf("%d",&n);for (int i=1;i<=n;i++) scanf("%d",&a[i]); int maxx=1;b[1]=1; for (i=2;i<=n;i++) { int maxn=0; for (j=i-1;j>=1;j--) if (a[i]>=a[j] && b[j]>maxn) maxn=b[j];b[i]=maxn+1;maxx=max(maxx,b[i]); }printf("%d\n",maxx);if (maxx==1) printf("%d\n%d",n,n);else { int i,j; for (i=2;i<=n;++i) for (j=1;j<i;++j) if (a[i]>=a[j]&&b[i]==b[j]+1) addline(j+n,i,1);for (i=1;i<=n;i++){if (b[i]==1) addline(0,i,1); addline(i,i+n,1);} for (i=n+1;i<=2*n;i++) if (b[i-n]==maxx) addline(i,n*2+1,1); int ans=dinic(0,n*2+1); printf("%d\n",ans); memset(point,-1,sizeof(point));memset(next,-1,sizeof(next));tot=-1;for (int i=2;i<=n;++i) for (int j=1;j<i;++j) if (a[i]>=a[j]&&b[i]==b[j]+1) addline(j+n,i,1);for (i=1;i<=n;i++){if (b[i]==1) addline(0,i,INF); addline(i,i+n,INF);} for (i=n+1;i<=2*n;i++) if (b[i-n]==maxx) addline(i,n*2+1,INF); int anss=dinic(0,n*2+1);printf("%d\n",anss); }}
总结:1.保证每个点只流一次的方法:每个点连相应的自己容量为1
0 0
- [codevs1906]最长递增子序列(dp+dinic)
- [codevs1906]最长递增子序列(dp+dinic)
- [网络流24题][codevs1906]最长递增子序列(dp+isap)
- 【codevs1906】最长递增子序列问题 最大流
- 【codevs1906】[网络流24题]最长递增子序列问题
- 最长递增子序列!!!(DP ,二分)
- 最长递增子序列(dp)
- 最长递增子序列 (dp)
- 最长递增子序列 - dp
- 最长递增子序列dp
- 最长公共子序列 最长递增子序列(和) 最长递增公共子序列 最长(连续)子序列乘积(HDU)--dp
- AOJ 189 最长递增子序列(DP)
- poj 1631Bridging signals Dp(最长递增子序列)
- NYOJ214最长单调递增子序列(DP)
- NYOJ 题目17 单调递增最长子序列 (DP)
- nyoj17单调递增最长子序列(dp)
- poj 2127 dp(最长公共递增子序列)
- POJ 1836 DP(最长递增子序列)
- Java传参练习
- View的事件分发机制总结
- Linux目录结构和常用命令(转载)
- 变量类型
- LUA string库详解
- [codevs1906]最长递增子序列(dp+dinic)
- Docker容器
- mac vim 常用命令
- TF-IDF及其算法
- 写高效的SQL语句
- VS2015 + EF6连接MYSQL
- Puzzle
- 框架之Hibernate(一)
- 搭建自己的Django应用(1)Writing your first Django app, part 1