妈蛋这道普及组水(神)题搞了我非常久。

一、

首先一个非常显然的事情就是每一个火车告诉了站与站之间的等级关系,所以拓扑求最长路。

可是发现暴力建边的话最坏能够达到500*500,所以时间复杂度有O(MN2)≈2.5∗108,常数相当小。

。数据水成狗,所以绝对能够过的。

二、

所以我就想到了bitset,把每辆火车做成一个长N的布尔向量。经过为1,不经过为0,第一个车站的左边和最后一个车站的右边补1,。

然后对于每一个车站,把全部它所在的位为1的向量都&起来,然后扫一遍向量连边。

这样做的时间复杂度能够用long long模拟bitset的时间复杂度来预计。就是O(MN264)≈107,常数更小了。实际跑起来事实上跟10^6差点儿相同。

三、

然后我看了一个大神的代码,发现原来是有正儿八经的O(NM)的做法的。

我们发现车站之间是比較麻烦的,所以考虑对偶转换!!

我们这样来考虑。比方说我们设火车经过的最低等级的车站为火车的等级,那么火车的等级数=车站的等级数?

依照上面的定义,火车的等级数自然是小于等于车站的等级数的。而假设一个车站不是不论什么一辆火车的等级,那么就意味着它能够下降或上升它自己的等级直到它是不论什么一辆火车的等级呢?

可是这种前提是每一辆车站都至少有一辆火车经过。所以自然我们仅仅要加一辆经过全部车站的火车就能够了。

这种话。我们仅仅须要求出火车的等级就可以了!

可是火车的等级怎么求呢?假设不存在一个车站使得两辆火车都经过它,那么显然这两辆火车之间是没有直接的等级关系的;而假设它们有交的话,那么显然在交集部分经过很多其它车站的火车的等级应该是更低的。由于低等级的车站会经过全部高等级的车站经过的车站!

一定要注意的地方:

①拓扑求最长路的时候是要求Max!!

②一定要对拍!

code(bitset):

#include<iostream>
using namespace std;
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
inline void in(int &x){
char c=getchar();
x=0;
while(c<'0'||c>'9')c=getchar();
for(;c>='0'&&c<='9';c=getchar())x=x*10+(c^'0');
}
int l[1005],r[1005];
#include<bitset>
bitset<1005> be[1005],btmp;
int next[1000005],ptr[1005],succ[1000005];
int stack[1005],level[1005],ru[1005];
int main(){
freopen("level2013.in","r",stdin);
freopen("level_TA.out","w",stdout);
int n,m,i,j,stop,s;
in(n),in(m);
for(i=m;i--;){
in(s);
in(l[i]);
for(--s;--s;){
in(stop);
be[i][stop]=1;
}
in(r[i]);
for(j=l[i];j;--j)be[i][j]=1;
for(j=r[i];j<=n;++j)be[i][j]=1;
}
int etot=1;
for(i=n;i;--i){
btmp.set();
for(j=m;j--;)
if(l[j]<=i&&i<=r[j]&&be[j][i]){
//cout<<"Get:"<<j<<endl;
btmp&=be[j];
}
for(j=n;j;--j)
if(~btmp[j]){
next[etot]=ptr[i],ptr[i]=etot,succ[etot++]=j;
//cout<<i<<"->"<<j<<":"<<ptr[i]<<"->"<<next[etot-1]<<endl;
++ru[j];
}
}
int top=0;
for(i=n;i;--i)
if(ru[i]==0){
stack[top++]=i;
level[i]=1;
//cout<<"First into stack:"<<i<<endl;
}
int nowlevel;
while(top--){
nowlevel=level[stack[top]];
//cout<<"----"<<stack[top]<<"-----\n";
for(i=ptr[stack[top]];i;i=next[i]){
level[succ[i]]=max(level[succ[i]],nowlevel+1);
//cout<<i<<":"<<nowlevel+1<<"->"<<succ[i]<<endl;
if(--ru[succ[i]]==0)stack[top++]=succ[i];
}
}
printf("%d\n",*max_element(level+1,level+n+1));
}

code(对偶转换):

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
inline void in(int &x){
char c=getchar();
while(c<'0'||c>'9')c=getchar();
x=0;
for(;c>='0'&&c<='9';c=getchar())x=x*10+(c^'0');
}
int num[1005][1005],stop[1005][1005];
int stack[1005];
int next[1000005],ptr[1005],succ[1000005],ru[1005],etot=1;
int level[1005];
inline void addedge(int u,int v){
next[etot]=ptr[u],ptr[u]=etot,++ru[v],succ[etot++]=v;
}
int main(){
freopen("level2013.in","r",stdin);
freopen("level2013.out","w",stdout);
int n,m,i,j,k,tmp;
in(n),in(m);
++m;
for(i=n;i;--i)num[0][i]=stop[0][i]=i;
stop[0][0]=n;
for(i=m;--i;){
in(stop[i][0]);
for(j=1,k=1;j<=stop[i][0];++j)
for(in(stop[i][j]);k<stop[i][j];++k)
num[i][k]=j-1;
--j;
while(k<=n)num[i][k++]=j;
}
int l,r;
for(i=m;i--;)
for(j=i;j--;){
l=max(stop[i][1],stop[j][1])-1;
r=min(stop[i][stop[i][0]],stop[j][stop[j][0]]);
if(l<=r)
if(num[i][r]-num[i][l]>num[j][r]-num[j][l])addedge(i,j);
else if(num[i][r]-num[i][l]<num[j][r]-num[j][l])addedge(j,i);
}
int top=0;
for(i=m;i--;)
if(!ru[i]){
stack[top++]=i;
level[i]=1;
}
int nowlevel;
while(top--){
nowlevel=level[stack[top]]+1;
for(i=ptr[stack[top]];i;i=next[i]){
level[succ[i]]=max(level[succ[i]],nowlevel);
if(!--ru[succ[i]])stack[top++]=succ[i];
}
}
printf("%d\n",*max_element(level,level+m));
}

最新文章

  1. PHP操作MySQL数据库5个步骤
  2. 探索Windows 8.1 Update 新功能点
  3. 中断处理流程,ok6410
  4. C输入输出函数与缓冲区
  5. bootstrap-validator验证问题总结
  6. winform里面网页显示指定内容
  7. C# WinForm PropertyGrid用法
  8. bzoj 2286: [Sdoi2011消耗战
  9. 网络资源管理系统LANsurveyor实战体验
  10. Lepus经历收获杂谈(一)——confirm features的小工具
  11. 转 XMLHttpRequest().readyState的五种状态详解
  12. properties配置文件中文乱码解决方法
  13. unity3d和php后台简单交互--一
  14. SpringMVC源码情操陶冶-HandlerAdapter适配器简析
  15. Kotlin 循环控制
  16. svn钩子
  17. 火狐扒代码插件ScrapBook
  18. LINK : fatal error LNK1123
  19. bootstrap组件-导出数据
  20. 创建一个接口Shape,其中有抽象方法area,类Circle 、Rectangle实现area方法计算其面积并返回。又有Star实现Shape的area方法,其返回值是0,Star类另有一返回值boolean型方法isStar;在main方法里创建一个Vector,根据随机数的不同向其中加入Shape的不同子类对象(如是1,生成Circle对象;如是2,生成Rectangle对象;如是3,生成S

热门文章

  1. CMSIS-RTOS 信号量
  2. python中的装饰器decorator
  3. gpdb删除segment上残余的session和sql
  4. struts2.x + Tiles2.x读取多个xml 配置文件
  5. KM最大匹配 HDU 2255
  6. 学习笔记 Java_静态_继承 2014.7.12
  7. TortoiseSvn介绍 客户端
  8. Ubuntu18.04上使用LLDB调试Chromium Android C++代码。
  9. ivms4200 远程桌面访问测试过程及问题汇总
  10. babel的插件