博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
洛谷 P1983 车站分级
阅读量:5019 次
发布时间:2019-06-12

本文共 3166 字,大约阅读时间需要 10 分钟。

嗯...

 

听说这是一道存图+拓扑排序的题,但是看了一晚上好像只看出存图来....

 

自己太蒟蒻,然后没办法,就.....就借用了Mr Kevin的代码和思路,然后自己做了一些了解...

 

(并且现在自己对拓扑排序还不是那么了解....

 

首先先看一下题吧:

 

一条单向的铁路线上,依次有编号为1,2,,nn个火车站。每个火车站都有一个级别,最低为1级。现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车站 x,则始发站、终点站之间所有级别大于等于火车站x的都必须停靠。

(注意:起始站和终点站自然也算作事先已知需要停靠的站点)例如,下表是5趟车次的运行情况。其中,前4趟车次均满足要求,而第 5 趟车次由于停靠了 3 号火车站(2级)却未停靠途经的 6号火车站(亦为2级)而不满足要求。

 

现有 m 趟车次的运行情况(全部满足要求),试推算这n个火车站至少分为几个不同的级别。

输入输出格式

输入格式:

第一行包含2个正整数n,m,用一个空格隔开。

i+1 行(1im)中,首先是一个正整数si(2sin),表示第i 趟车次有 si 个停靠站;接下来有si个正整数,表示所有停靠站的编号,从小到大排列。每两个数之间用一个空格隔开。输入保证所有的车次都满足要求。

输出格式:

一个正整数,即n个火车站最少划分的级别数。

输入输出样例

输入样例#1:
9 2 4 1 3 5 6 3 3 5 6
输出样例#1:
2
输入样例#2: 
9 3 4 1 3 5 6 3 3 5 6 3 1 5 9
输出样例#2:
3

说明

对于20%的数据,1n,m10;

对于 50%的数据,1n,m100;

对于 100%的数据,1n,m1000。

 

下面说一下自己的理解的思路:

 

首先对这个题要有正确的理解:  

1.  给出的一趟车,它所停靠的站点一定 >= 它所经过站点中级别最小的点一定 >= 起始点和终点;

2.  所有停靠的点的级别一定 > 未停靠的点;

3.  根据大于关系建立有向无环图(DAG) ,拓扑排序

 

 

所以,这道题的鬼畜之一在于——建图:

不是将火车停靠的车站与下一个停靠车站之间建图,而是将没停靠的站点与其下一个停靠的车站构造一个有向无环图(因为没停靠的车站的级别一定比停靠的车站的级别要低...

 

这道题的鬼畜之二在于一个优化:

实际上有最坏的情况,就是两个点之间连了很多条边(因为有很多趟车,不同趟的车可能经过相同的站点),容易炸空间,所以就用vis数组进行标记,来简化空间复杂度.....

 

所以,这道题的思路可分为:

 

优化读入----->建图+vis优化------>拓扑排序-------->输出答案

 

下面是AC代码:

1 #include 
2 #include
3 #include
4 5 using namespace std; 6 7 inline int get_num() {
//读入优化 8 int num = 0; 9 char c = getchar();10 while (c < '0' || c > '9') c = getchar();11 while (c >= '0' && c <= '9')12 num = num * 10 + c - '0', c = getchar();13 return num;14 }15 16 const int maxn = 1005;17 18 int graph[maxn][maxn], ind[maxn], stop[maxn], vis[maxn], level[maxn];19 //graph存图,ind存点的入度,stop存车站,vis是否访问(一个优化),level存车站的级别 20 queue
q;21 22 int main() {23 int n = get_num(), m = get_num(), ans = 0;24 for (int i = 1; i <= m; ++i) {25 int s = 0, t = 0, cnt = get_num();26 memset(stop, 0, sizeof(stop));27 memset(vis, 0, sizeof(vis));28 for (int j = 1; j <= cnt; ++j) {29 if (j == 1) vis[s = stop[j] = get_num()] = 1;//起点车站 30 else if (j == cnt) vis[t = stop[j] = get_num()] = 1;//终点车站 31 else vis[stop[j] = get_num()] = 1;//一般车站 32 } 33 for (int j = 1; j <= cnt; ++j) { 34 for (int k = s; k <= t; ++k)35 if (!vis[k] && !graph[k][stop[j]])//k车站没经过并且还没与车站j连成图 36 graph[k][stop[j]] = 1, ++ind[stop[j]];//构建有向无环图,j站入度+1 37 }38 }39 for (int i = 1; i <= n; ++i)40 if (!ind[i]) { //没有入度41 level[i] = 1;//将级别设为1 42 q.push(i);//入队,准备拓扑排序 43 }44 while (!q.empty()) {45 int u = q.front();//取队首 46 q.pop();47 for (int v = 1; v <= n; ++v)//遍历 48 if (graph[u][v]) {
//如果u点与v点有一条边 49 if (level[v] < level[u] + 1)50 level[v] = level[u] + 1;//更新操作,因为所要到达的车站一定比前面那个没有到达的车站的级别要高 51 if (!(--ind[v])) q.push(v);//toposort核心(判断入度,并入队 52 }53 if (ans < level[u]) ans = level[u];//更新答案54 }55 printf("%d", ans);56 return 0;57 }

 

 

难点在于建图,真搞不懂是如何想到这样建图的!!!

 

toposort也很重要!!!

 

转载于:https://www.cnblogs.com/New-ljx/p/10498483.html

你可能感兴趣的文章
从汇编看c++中的const常量
查看>>
在SQL中导入Excel数据时强制以文本类型导入
查看>>
[ZJOI2008]生日聚会
查看>>
React 配合echarts使用问题记录
查看>>
Remove Duplicates from Sorted Array
查看>>
下划线 动画
查看>>
小技巧分享:使用PostMessage向窗体传递任何数据
查看>>
Java数组初始化
查看>>
springboot+mybatis+dubbo+aop日志终结篇
查看>>
水晶报表 Crystal Report 调用存储过程时出错 找不到表 ,解决方法。
查看>>
leetcode_Multiply Strings
查看>>
Name和x:Name
查看>>
ELK 处理分析日志(nginx,syslog)
查看>>
kubeadm部署k8s-1.9
查看>>
dhtmlxTreeGrid使用
查看>>
Spring Security构建Rest服务-1203-Spring Security OAuth开发APP认证框架之短信验证码登录...
查看>>
记一次操作具有命名空间的xml文件遇到的问题
查看>>
Oracle数据字典
查看>>
Gulp 学习笔记
查看>>
【poj 3977】Subset (折半枚举)
查看>>