[第一波模拟\day3\T3]{益智游戏}(game.cpp)
【问题描述】
小P和小R在玩一款益智游戏。游戏在一个正权有向图上进行。
小P控制的角色要从A点走最短路到B点,小R控制的角色要从C点走最短路到D点。
一个玩家每回合可以有两种选择,移动到一个相邻节点或者休息一回合。
假如在某一时刻,小P和小R在相同的节点上,那么可以得到一次特殊奖励,但是在每个节点上最多只能得到一次。
求最多能获得多少次特殊奖励。
【输入格式】
第一行两个整数n,m表示有向图的点数和边数。
接下来m行每行三个整数xi,yi,li,表示从xi到yi有一条长度为li的边。
最后一行四个整数A,B,C,D,描述小P的起终点,小R的起终点。
【输出格式】
输出一个整数表示最多能获得多少次特殊奖励。若小P不能到达B点或者小R不能到达D点则输出-1。
【样例输入输出】
game.in |
game.out |
5 5 1 2 1 2 3 2 3 4 4 5 2 3 5 3 5 1 3 5 4 |
2 |
【数据规模】
对于30%的数据,满足n≤50
对于60%的数据,满足n≤1000,m≤5000
对于100%的数据,满足n≤50000,m≤200000,1≤li≤500000000
【题解】
为了处理出最短路径涉及的块,跑4遍最短路,也就是在原图和反向图上跑最短路对AB和CD各做1次
之后标记两个最短路网的边,被标记两次的就是两个人能相遇的边
对这些被标记的边建一个新图,跑拓扑排序+Dp找DAG的最长路,最长路经即为解
- #include <queue>
- #include <stdio.h>
- #include <string.h>
- #include <algorithm>
- #define oo 0x7fffffff - 1
- #define max(a, b) ((a) > (b) ? (a) : (b))
- using namespace std;
- inline int read()
- {
- int c = getchar(), x = 0;
- while(c < '0' || c > '9') c = getchar();
- while(c >= '0' && c <= '9') x = (x << 1) + (x << 3) + c - '0', c = getchar();
- return x;
- }
- int ans, n, m, A, B, C, D, cnt, ncnt, fcnt, h[50003], nh[50003], fh[50003], d1[50003], d2[50003], hash[200003], du[50003], Q[50003], f[50003];
- struct pt {int v, w, ne;} a[200003], na[200003], fa[200003];
- struct ed {int u, v, w;} e[200003];
- struct abcd {
- int fir, sec;
- bool operator < (const abcd oth) const {return sec > oth.sec;} };
- priority_queue<abcd> q;
- bool mark[50003];
- inline void link(int u, int v, int w) {a[++cnt].v = v, a[cnt].w = w, a[cnt].ne = h[u], h[u] = cnt;}
- inline void nlink(int u, int v, int w) {na[++ncnt].v = v, na[ncnt].w = w, na[ncnt].ne = nh[u], nh[u] = ncnt;}
- inline void flink(int u, int v, int w) {fa[++fcnt].v = v, fa[fcnt].w = w, fa[fcnt].ne = fh[u], fh[u] = fcnt;}
- void dijkstra(int x, int d[], pt a[], int h[])
- {
- for(int i = 1; i <= n; ++i) d[i] = oo, mark[i] = 0;
- d[x] = 0; q.push((abcd){x, 0});
- while(!q.empty())
- {
- int now = q.top().fir; q.pop();
- if(mark[now]) continue;
- mark[now] = 1;
- for(int j = h[now]; j; j = a[j].ne)
- if(!mark[a[j].v] && d[a[j].v] > d[now] + a[j].w)
- {
- d[a[j].v] = d[now] + a[j].w;
- q.push((abcd){a[j].v, d[a[j].v]});
- }
- }
- }
- bool preced()
- {
- dijkstra(A, d1, a, h);
- dijkstra(B, d2, na, nh);
- if(d1[B] == oo || d2[A] == oo) return 0;
- for(int j = 1; j <= m; ++j) if(d1[e[j].u] + e[j].w + d2[e[j].v] == d1[B]) ++hash[j];
- dijkstra(C, d1, a, h);
- dijkstra(D, d2, na, nh);
- if(d1[D] == oo || d2[C] == oo) return 0;
- for(int j = 1; j <= m; ++j)
- {
- if(d1[e[j].u] + e[j].w + d2[e[j].v] == d1[D]) ++hash[j];
- if(hash[j] == 2) {flink(e[j].u, e[j].v, e[j].w); ++du[e[j].v];}
- }
- return 1;
- }
- void sortdp()
- {
- for(int i = 1; i <= n; ++i) {f[i] = 1; if(!du[i]) Q[++Q[0]] = i;}
- for(int i = 1; i <= Q[0]; ++i)
- {
- int now = Q[i];
- for(int j = fh[now]; j; j = fa[j].ne)
- {
- f[fa[j].v] = max(f[fa[j].v], f[now] + 1);
- ans = max(ans, f[fa[j].v]);
- --du[fa[j].v];
- if(!du[fa[j].v]) Q[++Q[0]] = fa[j].v;
- }
- }
- printf("%d\n", ans);
- }
- int main()
- {
- freopen("game.in", "r", stdin), freopen("game.out", "w", stdout);
- n = read(), m = read();
- for(int i = 1; i <= m; ++i)
- {
- e[i].u = read(), e[i].v = read(), e[i].w = read();
- link(e[i].u, e[i].v, e[i].w);
- nlink(e[i].v, e[i].u, e[i].w);
- }
- A = read(), B = read(), C = read(), D = read();
- if(preced()) sortdp();
- else puts("-1");
- fclose(stdin), fclose(stdout);
- return 0;
- }
[第一波模拟\day3\T3]{益智游戏}(game.cpp)的更多相关文章
- [第一波模拟\day3\T2]{独立集}(bubble.cpp)
[问题描述] 有一天,一个名叫顺旺基的程序员从石头里诞生了.又有一天,他学会了冒泡排序和独立集.在一个图里,独立集就是一个点集,满足任意两个点之间没有边.于是他就想把这两个东西结合在一起.众所周知,独 ...
- 【2018.06.26NOIP模拟】T3节目parade 【支配树】*
[2018.06.26NOIP模拟]T3节目parade 题目描述 学校一年一度的学生艺术节开始啦!在这次的艺术节上总共有 N 个节目,并且总共也有 N 个舞台供大家表演.其中第 i 个节目的表演时间 ...
- 雅礼 noip2018 模拟赛 day3 T3
典型树形dp 这里,我们应该看到一些基本性质: ①:如果这个边不能改(不是没有必要改),我们就不改,因为就算改过去还要改回来,显然不是最优的 注意:"不能改"是指边的性质和要求的相 ...
- [第一波模拟\day1\T2]{分班}(divide.cpp)
[题目描述] 小N,小A,小T又大了一岁了. 现在,他们已经是高二年级的学生了.众所周知,高二的小朋友是要进行文理科分班考试的,这样子的话,三个好朋友说不定就会不分在一个班. 于是三个人决定,都考平均 ...
- [第一波模拟\day2\T1] {病毒分裂}(split.cpp)
[题目描述] A 学校的实验室新研制出了一种十分厉害的病毒.由于这种病毒太难以人工制造了,所以专家们在一开始只做出了一个这样的病毒.这个病毒被植入了特殊的微型芯片,使其可以具有一些可编程的特殊性能.最 ...
- NOIP欢乐模拟赛 T3 解题报告
3.小澳的葫芦 (calabash.cpp/c/pas) [题目描述] 小澳最喜欢的歌曲就是<葫芦娃>. 一日表演唱歌,他尽了洪荒之力,唱响心中圣歌. 随之,小澳进入了葫芦世界. 葫芦世界 ...
- 20161005 NOIP 模拟赛 T3 解题报告
subset 3.1 题目描述 一开始你有一个空集,集合可以出现重复元素,然后有 Q 个操作 1. add s 在集合中加入数字 s. 2. del s 在集合中删除数字 s.保证 s 存在 3. c ...
- 神奇的Noip模拟试题 T3 科技节 位运算
3 科技节 (scifest.pas/.c/.cpp) [问题描述] 一年一度的科技节即将到来.同学们报名各项活动的名单交到了方克顺校长那,结果校长一看皱了眉头:这帮学生热情竟然如此高涨,每个人都报那 ...
- ztz11的noip模拟赛T3:评分系统
代码: #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> ...
随机推荐
- MySql | 常用操作总结
创建数据库: CREATE DATABASE 数据库名; 删除数据库名: drop database <数据库名>; 选择数据库: use 数据库名; 创建数据表: CREATE TABL ...
- UWP 动画
一:StoryBoard 一般翻译成演示图版或者故事板,就像电影中的情节串联板,它是一个动画时间线的容器. 二:动画的分类 简单动画:以Animation结尾,例如DoubleAnimat ...
- 后缀数组 DC3构造法 —— 详解
学习了后缀数组,顺便把DC3算法也看了一下,传说中可以O(n)复杂度求出文本串的height,先比较一下倍增算法和DC3算法好辣. DC3 倍增法 时间复杂度 O(n)(但是常数很大) O(nlo ...
- MyBatsi-Mapper映射文件
Mapper映射文件 cache – 给定命名空间的缓存配置. cache-ref – 其他命名空间缓存配置的引用. resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加 ...
- select选择框中,model传的值并非是页面上的值,而是另一个值
对于编程来说,money和rebate代表的是金额优惠和折扣优惠,采用money或rebate便于数据存储.但是页面显示给用户的时候是金额优惠和折扣优惠,并不是显示编程中所存储数据.所以选择的mode ...
- Failure to transfer org.apache.maven.plugins:maven-compiler-plugin:jar:2.5.1
Mac上写了一段基于Maven的java代码. 上传Git后,在windows上pull下来,eclipse里面各种错误. ArtifactTransferException:Failure to t ...
- C# 移动开发(Xamarin.Form) Plugin.BLE 蓝牙连接
随着Xamarin.Form项目接近尾声,仔细一算才发现过来大半年时间了. 期间除了刚开始有闲情写写,现在总算有空来总结一下了. 来先说 Plugin.BLE (https://github.com/ ...
- ABAP和XML数据格式互相转换的两种方式
ABAP和XML数据格式互相转换是广大开发人员经常遇到的需求.本文介绍两种方式. 1. ABAP提供了一个工具类cl_proxy_xml_transform,通过它的两个方法abap_to_xml_x ...
- UGUI世界坐标转换为UI本地坐标
以下是实现hud跟随3D物体的脚本,只是测试用,不是开发中的代码,脚本挂在任意游戏物体上 demo下载 using UnityEngine; public class SceneFollowUI : ...
- 【软件构造】第三章第三节 抽象数据型(ADT)
第三章第三节 抽象数据型(ADT) 3-1节研究了“数据类型”及其特性 ; 3-2节研究了方法和操作的“规约”及其特性:在本节中,我们将数据和操作复合起来,构成ADT,学习ADT的核心特征,以及如何设 ...