题目大意

  一些火车站排成一行。给出一些火车的停靠站情况,要求对每一个火车,其经过且不停靠的站的级别比它任意停靠的站的级别小。问所有车站最少需要多少个级别。

题解

  不要只看到这道题的背景设立在一个区间上,就只想线段上的动规与贪心。由火车停靠站的情况可以得到不同站与不同站之间的级别满足偏序关系,这样就可以建立拓扑图求最长路径即可。

  普通建图$O(nm)$,要注意重边的情况,否则会MLE。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <stack>
#include <cassert>
using namespace std; const int MAX_NODE = 1010; struct TopGraph
{
private:
struct Node
{
vector<Node*> Next;
int Dist, DfsN;
}_nodes[MAX_NODE];
stack<Node*> St;
int TotNode; void Dfs(Node *cur)
{
if (cur->DfsN == 2)
return;
assert(cur->DfsN != 1);
cur->DfsN = 1;
for (int i = 0; i < cur->Next.size(); i++)
Dfs(cur->Next[i]);
cur->DfsN = 2;
St.push(cur);
} public:
void Init(int n)
{
TotNode = n;
} void AddEdge(int u, int v)
{
_nodes[u].Next.push_back(_nodes + v);
} int LongestPath()
{
for (int i = 1; i <= TotNode; i++)
Dfs(_nodes + i);
int ans = 0;
while (!St.empty())
{
Node *cur = St.top();
St.pop();
ans = max(ans, cur->Dist);
for (int i = 0; i < cur->Next.size(); i++)
cur->Next[i]->Dist = max(cur->Next[i]->Dist, cur->Dist + 1);
}
return ans;
}
}g; int stopPos[MAX_NODE];
bool Vis[MAX_NODE][MAX_NODE]; int main()
{
int len, trainCnt;
scanf("%d%d", &len, &trainCnt);
g.Init(len);
for (int i = 1; i <= trainCnt; i++)
{
int stopCnt;
scanf("%d", &stopCnt);
for (int j = 1; j <= stopCnt; j++)
scanf("%d", stopPos + j);
for (int j = 1; j < stopCnt; j++)
for (int k = stopPos[j] + 1; k <= stopPos[j + 1] - 1; k++)
for (int l = 1; l <= stopCnt; l++)
{
if (!Vis[k][stopPos[l]])
{
g.AddEdge(k, stopPos[l]);
Vis[k][stopPos[l]] = true;
}
}
}
printf("%d\n", g.LongestPath() + 1);
return 0;
}

  $O(n)$算法,对每个火车建立一个虚点,所有经过不停靠的站向虚点连边权1的边,虚点向所有停靠站连边权0的边,与原方法等价,却减少了时间复杂度。 

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <stack>
#include <cassert>
using namespace std; const int MAX_NODE = 2010; struct TopGraph
{
private:
struct Edge; struct Node
{
Edge *Head;
int Dist, DfsN;
}_nodes[MAX_NODE];
stack<Node*> St;
int TotNode; struct Edge
{
Node *To;
Edge *Next;
int Weight;
}_edges[MAX_NODE * MAX_NODE];
int _eCount; void Dfs(Node *cur)
{
if (cur->DfsN == 2)
return;
assert(cur->DfsN != 1);
cur->DfsN = 1;
for (Edge *e = cur->Head; e; e = e->Next)
Dfs(e->To);
cur->DfsN = 2;
St.push(cur);
} public:
void Init(int n)
{
TotNode = n;
} void AddEdge(int uId, int vId, int w)
{
Node *from = _nodes + uId, *to = _nodes + vId;
Edge *e = _edges + ++_eCount;
e->To = to;
e->Weight = w;
e->Next = from->Head;
from->Head = e;
} int LongestPath()
{
for (int i = 1; i <= TotNode; i++)
Dfs(_nodes + i);
int ans = 0;
while (!St.empty())
{
Node *cur = St.top();
St.pop();
ans = max(ans, cur->Dist);
for (Edge *e = cur->Head; e; e = e->Next)
e->To->Dist = max(e->To->Dist, cur->Dist + e->Weight);
}
return ans;
}
}g; int stopPos[MAX_NODE]; int main()
{
int len, trainCnt;
scanf("%d%d", &len, &trainCnt);
g.Init(len + trainCnt);
for (int i = 1; i <= trainCnt; i++)
{
int stopCnt;
scanf("%d", &stopCnt);
for (int j = 1; j <= stopCnt; j++)
scanf("%d", stopPos + j);
for (int j = 1; j < stopCnt; j++)
for (int k = stopPos[j] + 1; k <= stopPos[j + 1] - 1; k++)
g.AddEdge(k, len + i, 1);
for (int j = 1; j <= stopCnt; j++)
g.AddEdge(len + i, stopPos[j], 0);
}
printf("%d\n", g.LongestPath() + 1);
return 0;
}

  

luogu1980 车站分级的更多相关文章

  1. 洛谷P1983 车站分级

    P1983 车站分级 297通过 1.1K提交 题目提供者该用户不存在 标签图论贪心NOIp普及组2013 难度普及/提高- 提交该题 讨论 题解 记录 最新讨论 求帮忙指出问题! 我这么和(diao ...

  2. 【洛谷P1983】车站分级

    车站分级 题目链接 首先,可以发现火车停靠站点的大小是没有什么规律的, 火车可以停靠在级别<=当前级别的站点,必须停靠在级别>=当前最高级别的站点 但是所有没有被停靠的站点级别一定比所有被 ...

  3. 【NOIP2013 普及组】车站分级

    [NOIP2013 普及组]车站分级 一.题目 [NOIP2013 普及组]车站分级 时间限制: 1 Sec  内存限制: 128 MB 提交: 3  解决: 0 [提交][状态][讨论版] 题目描述 ...

  4. 洛谷P1983车站分级

    洛谷\(P1983\)车站分级(拓扑排序) 目录 题目描述 题目分析 思路分析 代码实现 题目描述 题目在洛谷\(P1983\)上 ​ 题目: 一条单向的铁路线上,依次有编号为 \(1, 2, -, ...

  5. 洛谷 P1983 车站分级

    题目链接 https://www.luogu.org/problemnew/show/P1983 题目描述 一条单向的铁路线上,依次有编号为 1,2,…,n的 n个火车站.每个火车站都有一个级别,最低 ...

  6. 洛谷P1983车站分级题解

    题目 这个题非常毒瘤,只要还是体现在其思维难度上,因为要停留的车站的等级一定要大于不停留的车站的等级,因此我们可以从不停留的车站向停留的车站进行连边,然后从入度为0的点即不停留的点全都入队,然后拓扑排 ...

  7. NOIp2013 车站分级 【拓扑排序】By cellur925

    题目传送门 我们注意到,题目中说:如果这趟车次停靠了火车站 x,则始发站.终点站之间所有级别大于等于火车站x的都必须停靠.有阶级关系,满满的拓扑排序氛围.但是,如果我们按大于等于的关系连,等于的情况就 ...

  8. [NOIP2013]车站分级 解题报告

    妈蛋这道普及组水(神)题搞了我非常久. 一. 首先一个非常显然的事情就是每一个火车告诉了站与站之间的等级关系,所以拓扑求最长路. 可是发现暴力建边的话最坏能够达到500*500,所以时间复杂度有O(M ...

  9. LG1983 「NOIP2013」车站分级 拓扑排序

    问题描述 LG1983 题解 考虑建立有向边\((a,b)\),代表\(a\)比\(b\)低级. 于是枚举每一辆车次经过的车站\(x \in [l,r]\),如果不是车辆停靠的车站,则从\(x\)向每 ...

随机推荐

  1. react杂记

    React webpack+react (hello world) 项目结构: src: app.js main.js package.json webpack_dev_config.js 需要安装包 ...

  2. 2017-5新版ionic3.1 新命令及一些常用命令

    ionic3.1的新命令: # ionic cordova --help //== 查看命令 # ionic cordova resources // 其中 icon.png (1024*1024) ...

  3. 移动web——touch事件介绍

    基本概念 1.在移动web端点击事件或者滑动屏幕.捏合等动作都是由touchstar.touchmove.touchend这三个事件组合在一起使用的 2.click事件在移动端会有0.2秒的延迟,下面 ...

  4. Ajax——php基础知识(二)

    header header('content-type:text/html; charset= utf-8');//设置编码格式为:utf-8 header('location:http://www. ...

  5. CSS——font

    行高的量取方式: 1.第一行可设置margin-top值.然后将第一文字顶部到第二行文字顶部的值作为行高的值(要注意对齐方式) 2.将 3.电视上 font:12px/1.5//字体12px,行高1. ...

  6. dubbo之延迟暴露

    延迟暴露 如果你的服务需要预热时间,比如初始化缓存,等待相关资源就位等,可以使用 delay 进行延迟暴露. 延迟 5 秒暴露服务 <dubbo:service delay="5000 ...

  7. Linux 一些小知识点汇总(持续更新....)

    一.符号 1.$@:传递的参数. 2.$# :传递参数的数量. 3.$?:指上一次执行命令后的返回值.一般0表示运行成功. 补充:$?只表示上一个命令执行后的退出状态,当命令执行后,又执行了其他命令, ...

  8. hibernate注解之@Onetomany、@Manytoone、@JoinColumn

    @Onetomany用于实体类与数据库表映射中少的一方,请看下面的例子. 假设一个用户只有一种角色,用户和角色是onetomany的关系 用户实体 @Entity @Table(name=" ...

  9. ubuntu下查看如何配置pycharm

    ubuntu中PyCharm的安装与卸载 https://blog.csdn.net/weixin_31484477/article/details/81133590 pycharm ModuleNo ...

  10. js 算法排序总结

    1.冒泡排序JavaScript代码实现: function bubbleSort(arr) { var len = arr.length; for (var i = 0; i < len; i ...