形式化题意

给定一个带权无向图,求从 \(s\) 点到 \(e\) 点的路径上途径边权种类的最小值.

思路

题图

我们把边权种类相同的点连成的子图抽象成一个 "平台" ,从题目给我们的图中可以看出来,\(1\) 到 \(6\) 的过程其实也是不断上平台与下平台的过程.

  1. 从 \(1\) 点上绿平台,走到 \(2\) 点下绿平台.
  2. 从 \(2\) 点上红平台,走到 \(6\) 点下红平台.

那么我们所求的种类数,不就是我们走过的不同平台数吗.

所以,我们现在需要维护这样一种规则:

  1. 在平台上走动不消耗费用
  2. 每上下平台记一次费用

其实十分容易实现. 一种是建分层图,一种是为每个平台建一个点,这里我们为了方便实现,说第二种.

现在我们为每个平台都建立起了一个点,那么为了使我们在平台上走动不消耗费用,我们需要将平台点与平台途径的每一个点都连接一条权值为 \(0\) 的无向边,为了使每上下平台记一次费用,我们可以只将所有上平台的边(即节点指向平台的边)的边权改为 \(1\),也可以只对下平台的边的值进行同样的操作.

这样,我们建立起的这个图就能跑最短路了,求出来的解即为答案.

优化

但是,这个题最恶心的地方是在它堆成山的 hack 数据(大概 90 多组),再加上这个题的多测,直接变成 TLE 测试机了. 所以,我们不得不对代码进行一些优化. 我的优化方案主要有以下几点:

1. 平台编号问题

假如我们直接使用 \(n+c\) ( \(c\)为平台编号 )作为平台点的 \(id\),会造成大量的空间浪费与清空消耗. 因此,我们采用有什么开什么的思想,建立一个 map,直接对输入值进行检测与分配编号,大概像下面这样:

map<int,int> mapping;
tot=n;
for(int i=1;i<=m;++i){
int x,y,z;
cin>>x>>y>>z;
if(!mapping.count){
mapping[z]=++tot;
}
e[x].push_back(edge{mapping[z],1});
e[y].push_back(edge{mapping[z],1});
e[mapping[z]].push_back(edge{x,0});
e[mapping[z]].push_back(edge{y,0});
}

但是这种办法在第三个测试点遗憾离场了: map 的查找复杂度太高,不得不把它改成一个 \(vis\) 和一个映射数组的组合,如下:

bool hv[400001];
int mapping[400001];
tot=n;
for(int i=1;i<=m;++i){
cin>>x>>y>>z;
if(!hv[z]){
hv[z]=true;
mapping[z]=++tot;
}
e[x].push_back(edge{mapping[z],1});
e[y].push_back(edge{mapping[z],1});
e[mapping[z]].push_back(edge{x,0});
e[mapping[z]].push_back(edge{y,0});
}
2. 初始化复杂度

请谨慎考虑你的代码的布局. 尽量不要出现初始化语句,任何的 memset,位运算赋值,clear() 都可能会导致你的代码慢上一千毫秒. 或者可以尽量减少初始化的范围,不要用 sizeof 浪费运行时间,用了哪里就只初始化哪里. 不然最好还是直接把 STL 的东西开成局部变量.

3. 判重

有 hack 数据重复了二十万次极限数据,请注意记录此次测试样例是否已经在之前的测试样例中被算出.

代码

未优化,仅用于参考,通过率很低
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m;
struct edge{
int to,w;
};
vector<edge> e[400001];
int dis[400001];
struct node{
int id,dis;
bool operator<(const node &A)const{
return dis>A.dis;
}
};
priority_queue<node> p;
bool vis[400001];
void dij(int s){
memset(dis,0x3f,sizeof(dis));
memset(vis,false,sizeof(vis));
dis[s]=0;
p.push(node{s,dis[s]});
while(!p.empty()){
node u=p.top();
p.pop();
if(vis[u.id]){
continue;
}
vis[u.id]=true;
for(edge i:e[u.id]){
if(dis[i.to]>dis[u.id]+i.w&&!vis[i.to]){
dis[i.to]=dis[u.id]+i.w;
p.push(node{i.to,dis[i.to]});
}
}
}
}
int tot=0;
bool hv[200001];
int mapping[200001];
signed main(){
ios::sync_with_stdio(false);
int cases;
cin>>cases;
while(cases--){
memset(hv,false,sizeof(hv));
memset(mapping,false,sizeof(mapping));
cin>>n>>m;
tot=n;int x,y,z;
for(int i=1;i<=m;++i){
cin>>x>>y>>z;
if(!hv[z]){
hv[z]=true;
mapping[z]=++tot;
}
e[x].push_back(edge{mapping[z],1});
e[y].push_back(edge{mapping[z],1});
e[mapping[z]].push_back(edge{x,0});
e[mapping[z]].push_back(edge{y,0});
}
int b,eu;
cin>>b>>eu;
dij(b);
cout<<dis[eu]<<endl;
for(int i=0;i<=tot;++i){
e[i].clear();
}
}
}

后记

好险,差点给我腰子噶断.

[TK] Rudolf and Subway ( CodeForces #933 div.3 - G )的更多相关文章

  1. Codeforces #344 Div.2

    Codeforces #344 Div.2 Interview 题目描述:求两个序列的子序列或操作的和的最大值 solution 签到题 时间复杂度:\(O(n^2)\) Print Check 题目 ...

  2. Codeforces #345 Div.1

    Codeforces #345 Div.1 打CF有助于提高做题的正确率. Watchmen 题目描述:求欧拉距离等于曼哈顿距离的点对个数. solution 签到题,其实就是求有多少对点在同一行或同 ...

  3. Codeforces Beta Round #27 (Codeforces format, Div. 2)

    Codeforces Beta Round #27 (Codeforces format, Div. 2) http://codeforces.com/contest/27 A #include< ...

  4. Educational Codeforces Round 39 (Rated for Div. 2) G

    Educational Codeforces Round 39 (Rated for Div. 2) G 题意: 给一个序列\(a_i(1 <= a_i <= 10^{9}),2 < ...

  5. Codeforces#441 Div.2 四小题

    Codeforces#441 Div.2 四小题 链接 A. Trip For Meal 小熊维尼喜欢吃蜂蜜.他每天要在朋友家享用N次蜂蜜 , 朋友A到B家的距离是 a ,A到C家的距离是b ,B到C ...

  6. codeforces #592(Div.2)

    codeforces #592(Div.2) A Pens and Pencils Tomorrow is a difficult day for Polycarp: he has to attend ...

  7. codeforces #578(Div.2)

    codeforces #578(Div.2) A. Hotelier Amugae has a hotel consisting of 1010 rooms. The rooms are number ...

  8. codeforces #577(Div.2)

    codeforces #577(Div.2) A  Important Exam A class of students wrote a multiple-choice test. There are ...

  9. Codeforces Round #582 (Div. 3)-G. Path Queries-并查集

    Codeforces Round #582 (Div. 3)-G. Path Queries-并查集 [Problem Description] 给你一棵树,求有多少条简单路径\((u,v)\),满足 ...

  10. codeforces #332 div 2 D. Spongebob and Squares

    http://codeforces.com/contest/599/problem/D 题意:给出总的方格数x,问有多少种不同尺寸的矩形满足题意,输出方案数和长宽(3,5和5,3算两种) 思路:比赛的 ...

随机推荐

  1. 关于导入react native项目导致运行异常的那些事

    从git上导入公司的项目,在本地运行的时候,项目无法运行.sdk,jdk,node都是使用公司规定的版本,项目中的local.properties文件sdk.dir路径也换成了自己本地的目录,结果就在 ...

  2. Python 按分类权重(区间)随机获取分类样本

    按分类权重(区间)随机获取分类样本 By:授客 QQ:1033553122 开发环境 win 10 python 3.6.5 需求 活动抽奖,参与抽奖产品有iphone, 华为,小米,魅族,vivo, ...

  3. AngleScript语法

    Class的使用要继承于Interface或者Mixin class.Mixinclass实际上就是类似于抽象类 ,它已经实现的,在子类里面不能实现,类似如下代码: interface AInterf ...

  4. jpa+querydsl的平替国产easy-query最好用的orm

    jpa+querydsl的平替国产easy-query最好用的orm 一款国产最强java orm,完美支持可控强类型dsl,外加完美支持对象模型筛选拉取的orm,拥有非常智能的include(s)一 ...

  5. 【MySQL】Windows-8.0.19 安装版 下载安装

    下载地址 https://dev.mysql.com/downloads/windows/installer/8.0.html 跳过登陆 只选择基本服务 安装依赖环境,如果已存在,圆圈显示绿点,下一步 ...

  6. 【SpringBoot】15 数据访问P3 整合Mybatis

    重新建立一个SpringBoot工程 选择依赖组件 然后删除不需要的Maven&Git文件 还是先查看我们的POM文件 整合Mybatis的组件多了这一个,默认的版本是3.5.4 然后再看看整 ...

  7. 模仿学习算法:Data Aggregation Approach: DAGGER算法——Mixing policy

    论文: <A Reduction of Imitation Learning and Structured Prediction to No-Regret Online Learning> ...

  8. apollo配置动态更新

    简单配置 使用@Value注解的配置会自动刷新配置 复杂对象 @Component("systemConfig") @ConfigurationProperties(prefix ...

  9. ucos cpu_a.asm 注释

    EXPORT CPU_SR_Save import:翻译为进口或引入,表明要调用的函数为外部文件定义 export:翻译为出口或输出,表明该符号可以被外部模块使用,类似于C中的extern功能. ;* ...

  10. C# 使用特性的方式封装报文

    在编写上位机软件时,需要经常处理命令拼接与其他设备进行通信,通常对不同的命令封装成不同的方法,扩展稍许麻烦. 本次拟以特性方式实现,以兼顾维护性与扩展性. 思想: 一种命令对应一个类,其类中的各个属性 ...