P3500【2015多校联训6】独立集(dp)
来源:互联网 发布:linux内核设计艺术pdf 编辑:程序博客网 时间:2024/06/03 17:54
题目大意: 求一数列的最大上升子序列+必定存在此最大上升子序列的点
题解
如果一个点必定存在与最长上升子序列中,那么必须满足两个条件:1.该点存在于最长上升子序列中。2.通过此点的最长上升子序列长度唯一。
但此题由于数据范围为1000005,所以常规n方求最长上升子序列的方法肯定不行,那么就考虑用树状数组维护小于当前值的最大上升子序列数即可。
如何判断一个点是否在最长上升子序列中?从前后各扫一遍如果前后的最长上升子序列想加的值等于最长上升自序列长度,那么该点一定在最长上升子序列中。
代码
#include<iostream>#include<algorithm>#include<cstdio>#include<cmath>#include<cstring>#include<queue>#include<vector>using namespace std;#define maxn 50005#define maxn1 200005#define ll long longconst long long inf=100000000000000LL;int n,m;int cnt,cnt1;int St[maxn1],End[maxn1],Next[maxn1],Last[maxn1],Len[maxn1];int End1[maxn1],Next1[maxn1],Last1[maxn1],Len1[maxn1];int End2[maxn1],Next2[maxn1],Last2[maxn1];ll dis[maxn][5];priority_queue<pair<ll,ll> >q;bool mark[maxn];int a,b,c,d;void dj(int x,int y){ int i,j; memset(mark,false,sizeof(mark)); for(i=1;i<=n;i++) dis[i][y]=inf; dis[x][y]=0; q.push(make_pair(0,x)); while(q.size()){ int t,s; t=q.top().second; s=-q.top().first; q.pop(); if(mark[t]) continue; mark[t]=true; for(i=Last[t];i;i=Next[i]){ int en=End[i]; if(dis[en][y]>s+Len[i]){ dis[en][y]=s+Len[i]; q.push(make_pair(-dis[en][y],en)); } } }}void dj2(int x,int y){ int i,j; memset(mark,false,sizeof(mark)); for(i=1;i<=n;i++) dis[i][y]=inf; dis[x][y]=0; q.push(make_pair(0,x)); while(q.size()){ int t,s; t=q.top().second; s=-q.top().first; q.pop(); if(mark[t]) continue; mark[t]=true; for(i=Last1[t];i;i=Next1[i]){ int en=End1[i]; if(dis[en][y]>s+Len1[i]){ dis[en][y]=s+Len1[i]; q.push(make_pair(-dis[en][y],en)); } } }}void insert(int x,int y,int z){ Next[++cnt]=Last[x]; Last[x]=cnt; End[cnt]=y; Len[cnt]=z; St[cnt]=x;}void insert1(int x,int y,int z){ Next1[cnt]=Last1[x]; Last1[x]=cnt; End1[cnt]=y; Len1[cnt]=z;}void insert2(int x,int y){ Next2[++cnt1]=Last2[x]; Last2[x]=cnt1; End2[cnt1]=y;}ll minl;int ru[maxn];bool jd[maxn],mark2[maxn];int ans=0;queue<int>tp;int dp[maxn];main(){// freopen("game.in","r",stdin);// freopen("game.out","w",stdout); int i,j; scanf("%d%d",&n,&m); for(i=1;i<=m;i++){ int x,y,z; scanf("%d%d%d",&x,&y,&z); insert(x,y,z); insert1(y,x,z); } scanf("%d%d%d%d",&a,&b,&c,&d); dj(a,1);dj(c,3); dj2(b,2);dj2(d,4); int minl=dis[b][1]+dis[d][3]; int minl1=dis[b][1],minl2=dis[d][3]; if(minl>=inf){ cout<<"-1";return 0; } for(i=1;i<=n;i++){ if(dis[i][1]+dis[i][2]+dis[i][3]+dis[i][4]==minl){ jd[i]=true; } } for(i=1;i<=n;i++) for(i=1;i<=m;i++){ int x=St[i],y=End[i]; if(dis[x][1]+dis[x][3]+Len[i]*2+dis[y][2]+dis[y][4]==minl){ insert2(x,y); ru[y]++; } } //建立新图 // for(i=1;i<=n;i++)cout<<chu[i]; for(i=1;i<=n;i++){ if(ru[i]==0){ tp.push(i); if(jd[i]) dp[i]=1; } } while(tp.size()){ int t=tp.front(); tp.pop(); for(i=Last2[t];i;i=Next2[i]){ int en=End2[i]; dp[en]=max(dp[en],dp[t]+1); ru[en]--; if(ru[en]==0) tp.push(en); } } for(i=1;i<=n;i++) ans=max(ans,dp[i]); cout<<ans;}
阅读全文
0 0
- P3500【2015多校联训6】独立集(dp)
- NKOJ 3500 独立集(dp)
- HDU 1520 Anniversary party(树形DP-最大独立集)
- hdu 2412 基础树形DP 树的最大独立集
- hdu1520 Anniversary party(最大独立集 树形dp)
- BZOJ 4316 小C的独立集 仙人掌DP
- 树的最大独立集——树形dp
- bzoj 4316: 小C的独立集 树形dp
- [BZOJ2162]男生女生(二分图带权独立集+dp)
- [仙人掌DP] BZOJ 4316 小C的独立集
- UVA 1220 树形dp 最大独立集+状态标记
- [BZOJ4316][仙人掌][DP]小C的独立集
- 动态规划----树型DP----树的最大独立集
- uva 1220 lrj-P282 最大独立集(树形dp)
- 树上的动态规划;树的最大独立集;刷表DP,子问题彼此独立没有交集; 无根树转化有根树;
- 独立集
- 独立集
- 独立集
- uvalive7040 / cf gym 100548 Color(2014 ICPC 西安 F)
- 20171024测试 爆炸 最低成绩
- 图——连通分量与深度优先遍历
- vuejs 幻灯片组件发开
- 小学生也能懂AI——白话监督学习
- P3500【2015多校联训6】独立集(dp)
- C语言热身——预处理指令、变量类型、static和extern、结构体、枚举
- hdu1166 敌兵布阵-----(线段树)
- Test 2017.10.30
- 15.3.1 InputStream和Reader
- 单例模式
- 【NOIP模拟】 (10.30) T1 比赛
- Python正则表达式(一)
- Redis 配置