题目链接

问题分析

比较明显的最短路模型。需要堆优化的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」大中锋的游乐场的更多相关文章

  1. [TJOI2019]大中锋的游乐场——最短路+DP

    题目链接: [TJOI2019]大中锋的游乐场 题目本质要求的还是最短路,但因为有第二维权值(汽水看成$+1$,汉堡看成$-1$)的限制,我们在最短路的基础上加上一维$f[i][j]$表示到达$i$节 ...

  2. 「ZJOI2016」大森林 解题报告

    「ZJOI2016」大森林 神仙题... 很显然线段树搞不了 考虑离线操作 我们只搞一颗树,从位置1一直往后移动,然后维护它的形态试试 显然操作0,1都可以拆成差分的形式,就是加入和删除 因为保证了操 ...

  3. LOJ#2230. 「BJOI2014」大融合

    LOJ#2230. 「BJOI2014」大融合 题目描述 小强要在$N$个孤立的星球上建立起一套通信系统.这套通信系统就是连接$N$个点的一个树.这个树的边是一条一条添加上去的. 在某个时刻,一条边的 ...

  4. 【LOJ】#3109. 「TJOI2019」甲苯先生的线段树

    LOJ#3109. 「TJOI2019」甲苯先生的线段树 发现如果枚举路径两边的长度的话,如果根节点的值是$x$,左边走了$l$,右边走了$r$ 肯定答案会是$(2^{l + 1} + 2^{r + ...

  5. 【题解】Luogu P5340 [TJOI2019]大中锋的游乐场

    原题传送门 没想到省选也会出这种题??! 实际就是一个带有限制的最短路 因为\(k<=10\),所以我们珂以暴力将每个点的权值分为[-k,k],为了方便我们珂以转化成[0,2k],将汉堡的权值记 ...

  6. [洛谷P5340][TJOI2019]大中锋的游乐场

    题目大意:有$n(n\leqslant10^4)$个点,$m(m\leqslant10^5)$条边的无向图,每个点有一个属性$A/B$,要求$|cnt_A-cnt_B|\leqslant k(k\le ...

  7. luogu P5340 [TJOI2019]大中锋的游乐场

    传送门 要求经过路径汉堡的点和可乐的点个数之差绝对值\(\le k\),所以可以考虑dp,\(f_{i,j}\)表示到点\(i\),汉堡的点个数减可乐的点的个数为\(j\)的最短距离,注意一下负下标处 ...

  8. @loj - 2092@ 「ZJOI2016」大森林

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 小 Y 家里有一个大森林,里面有 n 棵树,编号从 1 到 n. ...

  9. 【LOJ】#2230. 「BJOI2014」大融合

    题解 我现在真是太特么老年了 一写数据结构就颓废,难受 这题就是用lct维护子树 ???lct怎么维护子树 这样想,我们给每个点记录虚边所在的子树大小,只发生在Access和link的时候 这样的话我 ...

随机推荐

  1. MySQL日期时间函数大全

    1.获取当前时间+日期 函数now() mysql> select now(); +---------------------+ | now() | +--------------------- ...

  2. CE修改器使用教程 [入门篇]

    Cheat Engine 一般简称CE,是一个开放源代码的作弊软件,其功能包括:内存扫描.十六进制编辑器.调试工具,Cheat Engine 自身附带了外挂制作工具,可以用它直接生成外挂工具,CE可以 ...

  3. laravel 中使用es 流程总结

    1. query_string 2.mutil_match 3.match 4.should.must.bool 5.analysiz

  4. 笔记本电脑重装win7/win10系统教程

    由于笔记本第一次重装系统会出现系统装不上,还有出现找不到有效硬盘分区,等等问题,然后这篇文章主要讲解BIOS设置的方法,用此BIOS设置,电脑用原本安装系统的方式,能有效地解决以上问题,这有两种方法解 ...

  5. private修饰的方法可以通过反射访问,那么private的意义是什么?

    反射代码: package test; public class Person { private String userName= "Tom"; private void pla ...

  6. 权限(rwx)对于目录与文件的意义

    1-权限对于目录的意义 首先要明白的是目录主要的内容是记录文件名列表和子目录列表,而不是实际存放数据的地方. r权限:拥有此权限表示可以读取目录结构列表,也就是说可以查看目录下的文件名和子目录名,注意 ...

  7. hadopp 环境搭建

    前序: 首先准备三个虚拟机节点.  配置hosts文件:每个节点都 如下配置: vi /etc/hosts 1. 每个结点分别产生公私密钥 ssh-keygen -t dsa -P '' -f ~/. ...

  8. 用SVM处理XSS时,数据清洗打标数据标准化处理的方法和意义

    def get_len(url): return len(url) def get_url_count(url): if re.search('(http://)|(https://)', url, ...

  9. scrapy常用设置和注意点!!!!

    setting里的设置 HTTPERROR_ALLOWED_CODES = [405]   //这一条是忽略405错误退出进程,有可能跳到405页面,在parse注意判断,重新请求页面 爬虫里的设置 ...

  10. 第十篇.6、python并发编程之IO模型

    一 IO模型介绍 为了更好地了解IO模型,我们需要事先回顾下:同步.异步.阻塞.非阻塞 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非 ...