Luogu P1983 车站分级 题解 [ 绿 ] [ 拓扑排序 ] [ 图论建模 ] [ 虚点 ]
车站分级:很好的拓扑排序题,细节有点多。
图论建模
首先观察对于一条线路,我们可以从中直接得到什么信息:
假设这条线路的开头为 \(st\),结尾为 \(ed\),那么在 \([st,ed]\) 的车站中,没有被选入线路的点一定比选入线路的点的级数至少少 \(1\)。
对于这一点条件,我们就可以建模了。
和差分约束一样,我们从某个点起连到所有比其多 \(1\) 的点的有向边,边权赋为 \(1\)。
然后拓扑排序跑最长路即可。不是最短路的原因是这些都是充分必要条件,每一个都必须满足,因此要选最长路。
这样建图是 \(O(n^2m)\) 的,虽然常数小,但还是容易被卡。
优化
发现复杂度瓶颈在于是一堆点往一堆点连边,所以我们从优化建边的方式入手:虚点优化。
我们把那些原来的起点们连多条向这个虚点的有向边,边权赋为 \(0\);然后从这个虚点连多条向原来的终点们的有向边,边权赋为 \(1\),这样就可以在 \(O(n)\) 的时间里完成 \(O(n^2)\) 的建边了。
总体复杂度是 \(O(nm)\)。
细节
边权全部赋值为 \(1\) 的做法
对于这种做法,非常万能,但我想不到。
写这种做法细节很少,我们无需处理起点是 \(0\) 是 \(1\),直接全赋为 \(0\) 就好了,因为我们先不考虑起点。
最后统计答案的时候,我们只需要将 $ ans \div 2 +1$ 即可,\(\div2\) 是因为经过虚点一次会走两条边,要除回来;\(+1\) 是因为要加上起点。
同时注意有可能虚点入度为 \(0\),所以虚点也要加入拓扑排序的初始化中,比如下面的数据:
in:
3 1
2 1 2
out:
1
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m,a[1005],dp[3005],rd[3005],ans=0;
vector<int>g[3005];
queue<int>q;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int s,st=0,ed=0;
cin>>s;
bitset<1005>isin;
for(int j=1;j<=s;j++)
{
cin>>a[j];
isin[a[j]]=1;
if(j==1)st=a[j];
if(j==s)ed=a[j];
}
int vt=n+i;
for(int j=st;j<=ed;j++)
{
if(isin[j]==0)
{
g[j].push_back(vt);
rd[vt]++;
}
else
{
g[vt].push_back(j);
rd[j]++;
}
}
}
for(int i=1;i<=n+m;i++)
{
if(rd[i]==0)
{
q.push(i);
dp[i]=0;
}
}
while(!q.empty())
{
int u=q.front();
q.pop();
for(auto v:g[u])
{
dp[v]=max(dp[v],dp[u]+1);
rd[v]--;
if(rd[v]==0)
{
q.push(v);
}
}
}
for(int i=1;i<=n+m;i++)
{
ans=max(ans,dp[i]/2+1);
}
cout<<ans;
return 0;
}
对于边权先赋为 \(1\),后面再赋为 \(0\) 的做法
依然是上面的那个 hack 数据:
in:
3 1
2 1 2
out:
1
如果把入度为 \(0\) 的虚点的最长路也初始化为 \(1\) 的话,就会导致这组数据结果多一个 \(1\)。因此应该把虚点初始化为 \(0\),其他点初始化为 \(1\)。
另外,不要读错题了,只有起点和终点之间的车站才受分级的约束,而不是全部车站。
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m,a[1005],dp[3005],rd[3005],ans=0;
struct edge{
int to,w;
};
vector<edge>g[3005];
queue<int>q;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int s,st=0,ed=0;
cin>>s;
bitset<1005>isin;
for(int j=1;j<=s;j++)
{
cin>>a[j];
isin[a[j]]=1;
if(j==1)st=a[j];
if(j==s)ed=a[j];
}
int vt=n+i;
for(int j=st;j<=ed;j++)
{
if(isin[j]==0)
{
g[j].push_back({vt,0});
rd[vt]++;
}
else
{
g[vt].push_back({j,1});
rd[j]++;
}
}
}
for(int i=1;i<=n;i++)
{
if(rd[i]==0)
{
q.push(i);
dp[i]=1;
}
}
for(int i=n+1;i<=n+m;i++)
{
if(rd[i]==0)
{
q.push(i);
dp[i]=0;
}
}
while(!q.empty())
{
int u=q.front();
q.pop();
for(auto tmp:g[u])
{
int v=tmp.to,w=tmp.w;
dp[v]=max(dp[v],dp[u]+w);
rd[v]--;
if(rd[v]==0)
{
q.push(v);
}
}
}
for(int i=1;i<=n+m;i++)
{
ans=max(ans,dp[i]);
}
cout<<ans;
return 0;
}
Luogu P1983 车站分级 题解 [ 绿 ] [ 拓扑排序 ] [ 图论建模 ] [ 虚点 ]的更多相关文章
- 洛谷P1983车站分级题解
题目 这个题非常毒瘤,只要还是体现在其思维难度上,因为要停留的车站的等级一定要大于不停留的车站的等级,因此我们可以从不停留的车站向停留的车站进行连边,然后从入度为0的点即不停留的点全都入队,然后拓扑排 ...
- 【luogu P1983 车站分级】 题解
题目链接:https://www.luogu.org/problemnew/show/P1983 符合了NOIP命题的特点,知识点不难,思维量是有的. step1:把题读进去,理解.得到 非停靠点的等 ...
- Luogu P1983 车站分级
(一周没写过随笔了) 这道题有坑! 看到题目,发现这么明显(??)的要求顺序,还有什么想法,拓扑! 将每条路范围内等级大于等于它的点(不能重复(坑点1))和它连一条边,注意起点终点都要有(坑点2),然 ...
- 洛谷P1983 车站分级
P1983 车站分级 297通过 1.1K提交 题目提供者该用户不存在 标签图论贪心NOIp普及组2013 难度普及/提高- 提交该题 讨论 题解 记录 最新讨论 求帮忙指出问题! 我这么和(diao ...
- 洛谷P1983车站分级
洛谷\(P1983\)车站分级(拓扑排序) 目录 题目描述 题目分析 思路分析 代码实现 题目描述 题目在洛谷\(P1983\)上 题目: 一条单向的铁路线上,依次有编号为 \(1, 2, -, ...
- [LOJ 3101] [Luogu 5332] [JSOI2019]精准预测(2-SAT+拓扑排序+bitset)
[LOJ 3101] [Luogu 5332] [JSOI2019]精准预测(2-SAT+拓扑排序+bitset) 题面 题面较长,略 分析 首先,发现火星人只有死和活两种状态,考虑2-SAT 建图 ...
- NOIP 车站分级 (luogu 1983 & codevs 3294 & vijos 1851) - 拓扑排序 - bitset
描述 一条单向的铁路线上,依次有编号为 1, 2, ..., n 的 n 个火车站.每个火车站都有一个级别,最低为 1 级.现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车 ...
- 【基础练习】【拓扑排序】codevs3294 车站分级题解
题目来源:NOIP2013 普及第四题 题目描写叙述 Description 一条单向的铁路线上,依次有编号为1, 2, -, n的n个火车站.每一个火车站都有一个级别,最低为1级.现有若干趟车次在这 ...
- P1983 车站分级 思维+拓扑排序
很久以前的一道暑假集训的题,忘了补. 感觉就是思维建图,加拓扑排序. 未停靠的火车站,必然比停靠的火车站等级低,就可以以此来建边,此处注意用vis来维护一下,一个起点和终点只建立一条边,因为不这样的话 ...
- P1983 车站分级[拓扑]
题目描述 一条单向的铁路线上,依次有编号为 1, 2, -, n1,2,-,n的 nn个火车站.每个火车站都有一个级别,最低为 11 级.现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟 ...
随机推荐
- API 接口开发调试工具之ApiPost
安装 ApiPost ApiPost 支持 Windows.Mac.Linux 平台,你可以通过这个链接下载软件安装包: https://www.apipost.cn/download.html?fr ...
- 定时任务监控服务Healthchecks
GitHub地址:https://github.com/healthchecks/healthchecks 官方文档:https://healthchecks.io/docs/ 按照步骤进行安装: 1 ...
- 精橙FPGA,一个承接FPGA代码设计的资深工程师团队。
一.我们是谁 精橙FPGA,一个承接FPGA代码设计的资深工程师团队. 二.服务内容 面向在校学生.职场工程师等人员,提供FPGA入门指导和FPGA代码设计外包服务. 三.业务范围 主要提供Xilin ...
- 要构建此项目,必须安装以下工作负载: wasm-tools
要构建此项目,必须安装以下工作负载: wasm-tools 要安装这些工作负载,请运行以下命令: dotnet workload restore AdminAPP C:\Program Files\d ...
- Fuzz技术综述与文件Fuzz
文章一开始发表在微信公众号 https://mp.weixin.qq.com/s?__biz=MzUyNzc4Mzk3MQ==&mid=2247486189&idx=1&sn= ...
- AI 与数据的智能融合丨大模型时代下的存储系统
WOT 全球技术创新大会2024·北京站于 6 月 22 日圆满落幕.本届大会以"智启新纪,慧创万物"为主题,邀请到 60+ 位不同行业的专家,聚焦 AIGC.领导力.研发效能.架 ...
- GraphQL Part I: hello, world.
GraphQL with ASP.NET Core (Part- I : Hello World) 厌倦了 REST? 让我们谈一下 GraphQL, GraphQL 提供声明式的方式从服务器获取数据 ...
- remove a git submodule
参考: http://stackoverflow.com/questions/1260748/how-do-i-remove-a-submodule 1. Delete the relevant se ...
- 【sprinb-boot】@ComponentScan 跳过扫描 excludeFilters
@ComponentScan(excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Contr ...
- 浅谈 IoT 如何助力制造业企业实现数字化落地
物联网作为新一代信息技术的重要组成部分,正在加速渗透到各行各业,成为经济社会数字化转型的关键支撑.根据中商产业研究院发布的<2022-2027 年中国物联网市场需求预测及发展趋势前瞻报告> ...