[第一波模拟\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> ...
随机推荐
- spring+redis 报错 org.springframework.core.serializer.support.DeserializingConverter.<init>(Ljava/lang/ClassLoader;)V
这个问题的原因大概就是spring-data-redis.jar包版本不对 ,下面版本可以正常启动 <dependency> <groupId>org.springframew ...
- win32 指令大全
指令类型 助记符 (带*为特权指令) 对标志寄存器的影响 备注 说明 举例 ZF CF PF SF OF AF DF IF TF 数据传送类 数据传送 MOV 不影响标志位 Move MOV r/m3 ...
- Kruskal HDOJ 1233 还是畅通工程
题目传送门 /* 最小生成树之kruskal算法--并查集(数据结构)实现 建立一个结构体,记录两点和它们的距离,依照距离升序排序 不连通就累加距离,即为最小生成树的长度 */ #include &l ...
- eclipse XML TAB键默认为四个空格
- apache http server2.2 + tomcat5.5 性能调优
httpd加tomcat做负载均衡,采用session复制方式共享session,采用http-proxy连接方式,打开status mod 一.没有做httpd和tomcat的启动参数修改,包括jv ...
- 将php数组传递到js—json_encode(),json_decode()
json_decode(),对一个json字符串进行解码,json_encode()是生成一个json字符串 上面的解释很清楚了,关于php里数组赋值的问题,列举如下: <?php //对象 c ...
- 从零开始docker部署flask
1.下载一个Ubuntu镜像 2.启动镜像,使用apt-get安装python.安装pip,建议也装个vim吧 3.通过以上的容器生成一个新的镜像,命令如下docker commit afcaf46e ...
- 序列化json模块
1.用json模块来进行序列化和反序列化 注意:用json序列化的数据类型得到的文件后缀名必须是json.因为如果不是json后缀,别人也不知道这是用json序列化的文件. 序列化:json.dump ...
- 初学者可能不知道的vue技巧
前言 大家好,这里是@IT·平头哥联盟,我是首席甩锅官——老金,今天给大家分享的,一些日常中神秘而又简单的vue的实用小技巧,以及我在我司项目中实用vue的总结和坑,跟大家一起分享,希望能给其他攻城狮 ...
- Android一键锁屏APP
题记: 这个app完全是拾人牙慧,作为练手用的,其实没有什么原创的东西.当然,博客还是我自己写的,记录下来,对自己也算是一种成长吧. 转载请注明原文地址: http://www.cnblogs.com ...