「TJOI2019」大中锋的游乐场
问题分析
比较明显的最短路模型。需要堆优化的dij。建图的时候注意细节就好。
参考程序
#include <bits/stdc++.h>
#define LL long long
//#define DEBUG
using namespace std;
const int Maxn = 10010;
const int Maxm = 100010;
const int Maxk = 12;
struct edge {
int To, Next, Cost;
};
edge Edge[ Maxm << 1 ];
int Start[ Maxn ], Used;
int n, m, k, Tag[ Maxn ], Dis[ Maxn ][ Maxk << 1 ], s, t, Vis[ Maxn ][ Maxk << 1 ];
int DistK;
struct heap {
int Used, Tree[ Maxn * ( Maxk << 1 ) ], Ref[ Maxn * ( Maxk << 1 ) ];
void Clear() { Used = 0; return; }
bool Cmp( int x, int y ) {
return Dis[ x / DistK ][ x % DistK ] < Dis[ y / DistK ][ y % DistK ];
}
bool Empty() { return Used == 0; }
inline void Swap( int x, int y ) {
Ref[ Tree[ x ] ] = y;
Ref[ Tree[ y ] ] = x;
swap( Tree[ x ], Tree[ y ] );
return;
}
void Insert( int x ) {
++Used; Tree[ Used ] = x; Ref[ x ] = Used;
int Temp = Used;
for( ; Temp > 1; )
if( Cmp( Tree[ Temp ], Tree[ Temp >> 1 ] ) )
Swap( Temp, Temp >> 1 ), Temp >>= 1;
else
break;
return;
}
void Fresh( int x ) {
int Temp = Ref[ x ];
for( ; Temp > 1; )
if( Cmp( Tree[ Temp ], Tree[ Temp >> 1 ] ) )
Swap( Temp, Temp >> 1 ), Temp >>= 1;
else
break;
return;
}
int Top() { return Tree[ 1 ]; }
void Pop() {
Swap( 1, Used ); --Used;
int Temp = 1;
for( ; ( Temp << 1 ) <= Used; ) {
if( ( Temp << 1 | 1 ) > Used ) {
if( Cmp( Tree[ Temp << 1 ], Tree[ Temp ] ) )
Swap( Temp, Temp << 1 );
break;
}
if( Cmp( Tree[ Temp << 1 ], Tree[ Temp << 1 | 1 ] ) )
if( Cmp( Tree[ Temp << 1 ], Tree[ Temp ] ) ) {
Swap( Temp, Temp << 1 );
Temp <<= 1;
}
else
break;
else
if( Cmp( Tree[ Temp << 1 | 1 ], Tree[ Temp ] ) ) {
Swap( Temp, Temp << 1 | 1 );
Temp = Temp << 1 | 1;
}
else
break;
}
return;
}
};
heap Heap;
void Clear() {
memset( Start, 0, sizeof( Start ) );
Used = 0;
memset( Dis, 255, sizeof( Dis ) );
Heap.Clear();
return;
}
inline void AddEdge( int x, int y, int z ) {
Edge[ ++Used ] = ( edge ){ y, Start[ x ], z };
#ifdef DEBUG
printf( "AddEdge %d -> %d : %d\n", x, y, z );
#endif
Start[ x ] = Used;
return;
}
void Init() {
scanf( "%d%d%d", &n, &m, &k );
++k;
for( int i = 1; i <= n; ++i ) scanf( "%d", &Tag[ i ] );
for( int i = 1; i <= n; ++i ) Tag[ i ] = ( Tag[ i ] == 1 ) ? -1 : 1;
for( int i = 1; i <= m; ++i ) {
int x, y, z; scanf( "%d%d%d", &x, &y, &z );
AddEdge( x, y, z ); AddEdge( y, x, z );
}
scanf( "%d%d", &s, &t );
DistK = k << 1;
return;
}
void Work() {
Clear();
Init();
Dis[ s ][ k + Tag[ s ] ] = 0;
if( k + Tag[ s ] < 1 || k + Tag[ s ] >= DistK ) {
printf( "-1\n" );
return;
}
Heap.Insert( s * DistK + k + Tag[ s ] );
Vis[ s ][ k ] = 2;
for( ; !Heap.Empty(); ) {
int T = Heap.Top();
Heap.Pop();
int u = T / DistK;
Vis[ u ][ T % DistK ] = 1;
#ifdef DEBUG
printf( "Sol %d %d %d\n", u, T % DistK, Dis[ u ][ T % DistK ] );
#endif
for( int t = Start[ u ]; t; t = Edge[ t ].Next ) {
int v = Edge[ t ].To; int p = T % DistK + Tag[ v ];
if( p < 1 || p >= DistK ) continue;
if( Vis[ v ][ p ] == 1 ) continue;
if( Dis[ v ][ p ] == -1 ||
Dis[ v ][ p ] > Dis[ u ][ T % DistK ] + Edge[ t ].Cost ) {
Dis[ v ][ p ] = Dis[ u ][ T % DistK ] + Edge[ t ].Cost;
#ifdef DEBUG
printf( " Cha %d %d %d\n", v, p, Dis[ v ][ p ] );
#endif
if( Vis[ v ][ p ] == 2 ) Heap.Fresh( v * DistK + p );
else {
Heap.Insert( v * DistK + p );
Vis[ v ][ p ] = 2;
}
}
}
}
int Ans = -1;
for( int i = 1; i < DistK; ++i )
if( Dis[ t ][ i ] != -1 && ( Ans == -1 || Ans > Dis[ t ][ i ] ) )
Ans = Dis[ t ][ i ];
printf( "%d\n", Ans );
return;
}
int main() {
int TestCases; scanf( "%d", &TestCases );
for( ; TestCases--; ) Work();
return 0;
}
「TJOI2019」大中锋的游乐场的更多相关文章
- [TJOI2019]大中锋的游乐场——最短路+DP
题目链接: [TJOI2019]大中锋的游乐场 题目本质要求的还是最短路,但因为有第二维权值(汽水看成$+1$,汉堡看成$-1$)的限制,我们在最短路的基础上加上一维$f[i][j]$表示到达$i$节 ...
- 「ZJOI2016」大森林 解题报告
「ZJOI2016」大森林 神仙题... 很显然线段树搞不了 考虑离线操作 我们只搞一颗树,从位置1一直往后移动,然后维护它的形态试试 显然操作0,1都可以拆成差分的形式,就是加入和删除 因为保证了操 ...
- LOJ#2230. 「BJOI2014」大融合
LOJ#2230. 「BJOI2014」大融合 题目描述 小强要在$N$个孤立的星球上建立起一套通信系统.这套通信系统就是连接$N$个点的一个树.这个树的边是一条一条添加上去的. 在某个时刻,一条边的 ...
- 【LOJ】#3109. 「TJOI2019」甲苯先生的线段树
LOJ#3109. 「TJOI2019」甲苯先生的线段树 发现如果枚举路径两边的长度的话,如果根节点的值是$x$,左边走了$l$,右边走了$r$ 肯定答案会是$(2^{l + 1} + 2^{r + ...
- 【题解】Luogu P5340 [TJOI2019]大中锋的游乐场
原题传送门 没想到省选也会出这种题??! 实际就是一个带有限制的最短路 因为\(k<=10\),所以我们珂以暴力将每个点的权值分为[-k,k],为了方便我们珂以转化成[0,2k],将汉堡的权值记 ...
- [洛谷P5340][TJOI2019]大中锋的游乐场
题目大意:有$n(n\leqslant10^4)$个点,$m(m\leqslant10^5)$条边的无向图,每个点有一个属性$A/B$,要求$|cnt_A-cnt_B|\leqslant k(k\le ...
- luogu P5340 [TJOI2019]大中锋的游乐场
传送门 要求经过路径汉堡的点和可乐的点个数之差绝对值\(\le k\),所以可以考虑dp,\(f_{i,j}\)表示到点\(i\),汉堡的点个数减可乐的点的个数为\(j\)的最短距离,注意一下负下标处 ...
- @loj - 2092@ 「ZJOI2016」大森林
目录 @description@ @solution@ @accepted code@ @details@ @description@ 小 Y 家里有一个大森林,里面有 n 棵树,编号从 1 到 n. ...
- 【LOJ】#2230. 「BJOI2014」大融合
题解 我现在真是太特么老年了 一写数据结构就颓废,难受 这题就是用lct维护子树 ???lct怎么维护子树 这样想,我们给每个点记录虚边所在的子树大小,只发生在Access和link的时候 这样的话我 ...
随机推荐
- 总结 | 慢 SQL 问题经验总结
1. 导致慢 SQL 的原因 在遇到慢 SQL 情况时,不能简单的把原因归结为 SQL 编写问题(虽然这是最常见的因素),实际上导致慢 SQL 有很多因素,甚至包括硬件和 mysql 本身的 bug. ...
- Vue初始化一个项目
@1 npm install -g @vue/cli-init vue init webpack projectName @2 cnpm install -g @vue/cli vue create ...
- 直通BAT必考题系列:JVM性能调优的6大步骤,及关键调优参数详解
JVM内存调优 对JVM内存的系统级的调优主要的目的是减少GC的频率和Full GC的次数. 1.Full GC 会对整个堆进行整理,包括Young.Tenured和Perm.Full GC因为需要对 ...
- iOS响应链和传递机制
iOS中加载的时候会先执行main函数 int main(int argc, charchar * argv[]) { @autoreleasepool { return UIApplicationM ...
- go语言的学习之路
一.学习前言 (1)go语言的介绍 1.解释型语言:python PHP java scripy (前端) 2.编译型语言:C C++ C#(微软开发) java(sun公司开发 后来被甲 ...
- 查看Linux服务器硬件信息
一:查看cpu# 总核数 = 物理CPU个数 X 每颗物理CPU的核数 # 总逻辑CPU数 = 物理CPU个数 X 每颗物理CPU的核数 X 超线程数# 查看物理CPU个数cat /proc/cpui ...
- openstack Rocky系列之keystone:(二)keystone中API注册
主要说一下initialize_application中的application_factory def loadapp(): app = application.application_factor ...
- zencart只有购买过此产品的客户才能评价产品
当前登录的客户买过此产品时,才显示评价按钮: <?php $rev_query = "select count(*) as count from orders o ,orders_pr ...
- maven地址配置为阿里maven仓库,附ali maven官方指南链接
一.参考链接 官方指南 链接地址:https://help.aliyun.com/document_detail/102512.html?spm=a2c40.aliyun_maven_repo.0.0 ...
- shell_hive
(1)获取参数:从shell文件传来参数,调用:$1,$2,$3 load_date=$1 clearn_date=`date -d"$2 day ago $load_date" ...