luogu1980 车站分级
题目大意
一些火车站排成一行。给出一些火车的停靠站情况,要求对每一个火车,其经过且不停靠的站的级别比它任意停靠的站的级别小。问所有车站最少需要多少个级别。
题解
不要只看到这道题的背景设立在一个区间上,就只想线段上的动规与贪心。由火车停靠站的情况可以得到不同站与不同站之间的级别满足偏序关系,这样就可以建立拓扑图求最长路径即可。
普通建图$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 车站分级的更多相关文章
- 洛谷P1983 车站分级
P1983 车站分级 297通过 1.1K提交 题目提供者该用户不存在 标签图论贪心NOIp普及组2013 难度普及/提高- 提交该题 讨论 题解 记录 最新讨论 求帮忙指出问题! 我这么和(diao ...
- 【洛谷P1983】车站分级
车站分级 题目链接 首先,可以发现火车停靠站点的大小是没有什么规律的, 火车可以停靠在级别<=当前级别的站点,必须停靠在级别>=当前最高级别的站点 但是所有没有被停靠的站点级别一定比所有被 ...
- 【NOIP2013 普及组】车站分级
[NOIP2013 普及组]车站分级 一.题目 [NOIP2013 普及组]车站分级 时间限制: 1 Sec 内存限制: 128 MB 提交: 3 解决: 0 [提交][状态][讨论版] 题目描述 ...
- 洛谷P1983车站分级
洛谷\(P1983\)车站分级(拓扑排序) 目录 题目描述 题目分析 思路分析 代码实现 题目描述 题目在洛谷\(P1983\)上 题目: 一条单向的铁路线上,依次有编号为 \(1, 2, -, ...
- 洛谷 P1983 车站分级
题目链接 https://www.luogu.org/problemnew/show/P1983 题目描述 一条单向的铁路线上,依次有编号为 1,2,…,n的 n个火车站.每个火车站都有一个级别,最低 ...
- 洛谷P1983车站分级题解
题目 这个题非常毒瘤,只要还是体现在其思维难度上,因为要停留的车站的等级一定要大于不停留的车站的等级,因此我们可以从不停留的车站向停留的车站进行连边,然后从入度为0的点即不停留的点全都入队,然后拓扑排 ...
- NOIp2013 车站分级 【拓扑排序】By cellur925
题目传送门 我们注意到,题目中说:如果这趟车次停靠了火车站 x,则始发站.终点站之间所有级别大于等于火车站x的都必须停靠.有阶级关系,满满的拓扑排序氛围.但是,如果我们按大于等于的关系连,等于的情况就 ...
- [NOIP2013]车站分级 解题报告
妈蛋这道普及组水(神)题搞了我非常久. 一. 首先一个非常显然的事情就是每一个火车告诉了站与站之间的等级关系,所以拓扑求最长路. 可是发现暴力建边的话最坏能够达到500*500,所以时间复杂度有O(M ...
- LG1983 「NOIP2013」车站分级 拓扑排序
问题描述 LG1983 题解 考虑建立有向边\((a,b)\),代表\(a\)比\(b\)低级. 于是枚举每一辆车次经过的车站\(x \in [l,r]\),如果不是车辆停靠的车站,则从\(x\)向每 ...
随机推荐
- Manacher 学习笔记
\(\\\) \(Manacher\) 一种常用的字符串算法,用于处理一些回文字符相关的问题. 回文串:从前向后和从后向前输出一致. 回文中心:以这里开始,每次向外左右各扩展一个字符得到的回文串的中心 ...
- 搭建本地wordpress
1.首先,下载xampp,安装按默认勾选即可. 2.安装完成后,启动Apache和MySQL这两个服务. 启动后变成绿色,表示启动成功. 3.点击MySQL项的Admin进入数据库后台. 4.点击用户 ...
- JS——思维拓展
1.阶乘求和:4的阶乘是1*2*3*4 <script> function jiechen(value) { var n = 1; for (var i = 1; i <= valu ...
- C# 配置文件ini操作类
// [ DllImport ( "kernel32" ) ] //private static extern long WritePrivateProfileString ( s ...
- mysql命令行导出数据
1. 包含表头 mysql -h${1} -P${2} -u${3} -p${4} -Dpom_${5} --default-character-set=utf8 -B -e > result. ...
- python函数参数的区别
在运用python的过程中,发现当函数参数为list的时候,在函数内部调用list.append()会改变形参,与C/C++的不太一样,查阅相关资料,在这里记录一下. python中id可以获取对象的 ...
- Win10电脑如何更改开机启动项
https://jingyan.baidu.com/article/5970355284f0458fc1074049.html
- 谷歌通过ajax获取本地JSON文件,为什么会提示跨域?
在本地写了一段JSON代码,然后用ajax读取后,在浏览器打开,发现谷歌提示涉及到跨域问题, 但是跨域是由于协议,域名,端口中有一个不同,才会跨域,我在本地访问自己的文件,怎么和跨域扯上关系了?? 下 ...
- kvm virt-install 使用小结
简介: virt-install 能够为KVM.Xen或其它支持libvrit API的hypervisor创建虚拟机并完成GuestOS安装. 此外,它能够基于串行控制台.VNC或SDL支持文本或图 ...
- jquery 对 table 的操作
<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head><meta ...