题目大意

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

题解

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

  普通建图$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. jQuery中国各个省份地图分部代码

    jQuery中国各个省份地图分部代码 在线演示本地下载

  2. js基础---数字日期及运算

    显示年月日 var a=new Date; console.log(a); var year=a.getFullYear(); var month=a.getMonth()+1; var day=a. ...

  3. 最容易理解的CSS的position教程——十步图解CSS的position

    CSS的positon,我想做为一个Web制作者来说都有碰到过,但至于对其是否真正的了解呢?那我就不也说了,至少我自己并不非常的了解其内核的运行.今天在Learn CSS Positioning in ...

  4. html中保证中文能够正常显示

    <meta http-equiv="Content-Type" content="text/html"; charset=utf-8"/> ...

  5. Android 在fragment中实现返回键单击提醒 双击退出

    尝试用mvp架构加dagger2来重写了一下,大致功能都实现了,还没有全部完成. 项目地址 接近完成的时候,想在天气信息页面实现一个很常见的功能,也就是点击屏幕下方的返回键的时候不是返回到上一个act ...

  6. Android_撕衣服小案例

    一直都觉得做安卓开发挺有意思,最近一段时间都在学习这方面的知识以及练习敲代码这次要说的是一个简单有趣的案例,相信大家也是看了标题才进来的吧,是不是有点迫不及待的想看看效果图,嘿嘿,算了还是直接给上源码 ...

  7. Core 项目下使用SQl语句

    public static DataTable ExeQuery(string connectionString, CommandType cmdType, string cmdText) { usi ...

  8. Spring学习笔记_day01_ioc

    本文为博主辛苦总结,希望自己以后返回来看的时候理解更深刻,也希望可以起到帮助初学者的作用. 转载请注明 出自 : luogg的博客园 谢谢配合! Spring_day01 spring是一站式的框架, ...

  9. Discuz! X3.1云平台QQ互联的Unknown column 'conuintoken' in 'field list' 解决办法

    http://www.discuz.net/thread-3482497-1-1.html 由于程序安装默认数据表的结构和QQ互联数据表结构不同,安装Discuz! X3.1和升级Discuz! X3 ...

  10. 使用ScriptManager服务器控件前后台数据交互

    前台页面信息: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebFor ...