[TK] Rudolf and Subway ( CodeForces #933 div.3 - G )
形式化题意
给定一个带权无向图,求从 \(s\) 点到 \(e\) 点的路径上途径边权种类的最小值.
思路
题图

我们把边权种类相同的点连成的子图抽象成一个 "平台" ,从题目给我们的图中可以看出来,\(1\) 到 \(6\) 的过程其实也是不断上平台与下平台的过程.
- 从 \(1\) 点上绿平台,走到 \(2\) 点下绿平台.
- 从 \(2\) 点上红平台,走到 \(6\) 点下红平台.
那么我们所求的种类数,不就是我们走过的不同平台数吗.
所以,我们现在需要维护这样一种规则:
- 在平台上走动不消耗费用
- 每上下平台记一次费用
其实十分容易实现. 一种是建分层图,一种是为每个平台建一个点,这里我们为了方便实现,说第二种.
现在我们为每个平台都建立起了一个点,那么为了使我们在平台上走动不消耗费用,我们需要将平台点与平台途径的每一个点都连接一条权值为 \(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 )的更多相关文章
- Codeforces #344 Div.2
		Codeforces #344 Div.2 Interview 题目描述:求两个序列的子序列或操作的和的最大值 solution 签到题 时间复杂度:\(O(n^2)\) Print Check 题目 ... 
- Codeforces #345 Div.1
		Codeforces #345 Div.1 打CF有助于提高做题的正确率. Watchmen 题目描述:求欧拉距离等于曼哈顿距离的点对个数. solution 签到题,其实就是求有多少对点在同一行或同 ... 
- Codeforces Beta Round #27 (Codeforces format, Div. 2)
		Codeforces Beta Round #27 (Codeforces format, Div. 2) http://codeforces.com/contest/27 A #include< ... 
- 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 < ... 
- Codeforces#441 Div.2 四小题
		Codeforces#441 Div.2 四小题 链接 A. Trip For Meal 小熊维尼喜欢吃蜂蜜.他每天要在朋友家享用N次蜂蜜 , 朋友A到B家的距离是 a ,A到C家的距离是b ,B到C ... 
- codeforces #592(Div.2)
		codeforces #592(Div.2) A Pens and Pencils Tomorrow is a difficult day for Polycarp: he has to attend ... 
- codeforces #578(Div.2)
		codeforces #578(Div.2) A. Hotelier Amugae has a hotel consisting of 1010 rooms. The rooms are number ... 
- codeforces #577(Div.2)
		codeforces #577(Div.2) A Important Exam A class of students wrote a multiple-choice test. There are ... 
- Codeforces Round #582 (Div. 3)-G. Path Queries-并查集
		Codeforces Round #582 (Div. 3)-G. Path Queries-并查集 [Problem Description] 给你一棵树,求有多少条简单路径\((u,v)\),满足 ... 
- codeforces #332 div 2 D. Spongebob and Squares
		http://codeforces.com/contest/599/problem/D 题意:给出总的方格数x,问有多少种不同尺寸的矩形满足题意,输出方案数和长宽(3,5和5,3算两种) 思路:比赛的 ... 
随机推荐
- wails实现腾讯元器bot
			简单记录工具的一个模块 后端 Api调用 登录 腾讯元器 后创建智能体,按自己的需求来创建,发布后要等等审核.  等发布完成后点击调用api即可,这里可以看到user_id, assistant ... 
- PHP现代化构建工具: 无需修改任何代码和扩展将你的ThinkPHP项目性能提高20倍
			我要分享一个令人激动的黑科技:PRipple 使用这个项目能够在无需修改任何代码且无需第三方扩展的前提下,将你的 Laravel 项目性能提高 20 倍.他仅仅依赖于PHP原生的 pcntl/posi ... 
- 如何正确使用@Bulider与<T>返回数据
			@Data @ToString @Builder @AllArgsConstructor public class PageResult<T> implements Serializabl ... 
- 修复ERROR 1045 (28000): Access denied for user 'root'@'%' (using password: YES)
			修复ERROR 1045 (28000): Access denied for user 'root'@'%' (using password: YES) 直接修改 mysql.user 表中的权限字 ... 
- mysql索引失效的情况七字口诀:“模型数空运最快”
			mysql索引失效的情况 七字口诀:"模型数空运最快" 模:使用like进行模糊查询的时候,以百分号%开头的,索引就会失效. 型:代表数据类型,数据类型错误了,索引也会失效. 数: ... 
- js实现动态表格的添加
			<!DOCTYPE html> <html lang="en"> <head> <title>Table_Simple CSS fo ... 
- 【SpringMVC】 Controller接收深度复杂对象封装不到的问题
			首先来看数据结构的定义: 一个Form对象,然后里面有一个排版日期对象的List集合 排班集合的每个元素中又有一个String集合 在前端的Post请求中可以看到这个String集合是传递了的 但是D ... 
- 【MQTT】Mosquitto 入门案例
			参考博主StoneGeek的文章 https://www.cnblogs.com/sxkgeek/p/9140180.html 之前接触的是在应用程序之间的消息中间件技术 RabbitMQ, Kafk ... 
- 【MySQL】重装Win10系统后恢复MySQL
			因为种种原因把系统重装了,安装的MySQL不在C盘中,所以数据不会被系统格式化掉 但是重装系统就把之前CMD声明的MySQL服务给删除了 要让MySQL重新跑起来,就需要重新安装服务 恢复MYSQL博 ... 
- 【Docker】09 部署挂载本地目录的Redis
			1.拉取Redis镜像: docker pull redis:6.0.6 2.执行挂载命令: docker run -d \ --name=redis \ --restart=always \ --p ... 
