NOIP模拟赛(by hzwer) T3 小奇回地球
【题目背景】
开学了,小奇在回地球的路上,遇到了一个棘手的问题。
【问题描述】
简单来说,它要从标号为 1 的星球到标号为 n 的星球,某一些星球之间有航线。 由于超时空隧道的存在,从一个星球到另一个星球时间可能会倒流,而且,从星 球 a 到 b 耗费的时间和星球 b 到 a 耗费的时间不一定相同。宇宙法规定:“禁止在出发时间前到达目的地”。每艘飞船上都有速度调节装置,可以调节飞行的时间。其功能可以使得整次航程中所有两星球间的飞行时间增加或减少相同的整数值。你的任务是帮助它调整速度调节器,找出一条最短时间到达目的地的路径。
【输入格式】
输入文件包含多组数据,第 1 个数为 T,表示数据组数。对于每组数据,输入第 1 行为两个正整数 n,m,为星球的个数和星球间的路线数。接下来 m 行,每行三个整数 i,j 和 t,表示由星球 i 到星球 j 飞行的时间为 t。由 i 到 j 最多只会有一条飞行线路。
【输出格式】
输出文件共 T 行,每组数据输出一行。
如果可以通过调节速度调节器完成任务,则输出一个非负整数,表示由星球1到星球 n 的最短时间。(注意最短时间要大于或者等于 0)。如果不能由星球 1 到达星球 n,则输出-1。
【样例输入】
1
4 5
1 2 1
1 3 1
2 3 -3
3 1 1
3 4 1
【样例输出】
2
【样例解释】
把速度控制器的值设为 1,相当于每个时间值加 1,得到的最短路径为 1→2→3→4。所需时间为 2+(-2)+2=2。
【数据范围】
1,2 号测试点,保证所有星球出度不超过1
3,4 号测试点,n<=10
5,6 号测试点,-100<=t<=100
对于 100%的数据 T<=10,n<=100,m<=n*(n-1),-100000<=t<=100000
数据随机和构造结合生成
【解析】
将此题简化后可得如下模型:给定一张有向图(有负边权),可以使每一条边加上或减去一个值t,使从1到n的最短路径最小且非负。
经过分析可以知道,若给每一条边加上一个值t0后,1到n的最短路为负,那么对于任意t<t0都有最短路径仍为负。由此可以想到二分答案。t的值域为-100000到100000,那么二分的左右边界就定好了。然后每次都用SPFA检验最短路径是否大于等于0,然后......死循环了。
为什么呢?假设有t1<0,那么图中就有几率出现负权环,那么就没有最短路。所以要在SPFA中加入判断负权环的内容。但即使这样仍会超时。那么我们继续思考怎么优化。显然,如果一个点与1或n不连通,那么它对答案是没有贡献的。我们先从1出发遍历整张图,把无法到达的点删去。然后再从1能够到达的点出发,如果该点不能到达n,也从集合中删去。在“砍图”之后,虽然时间已经优化了,但仍然不够。题目中有一句话是这么说的:
数据随机和构造结合生成
那是不是会卡SPFA呢?所以,一个神奇的操作就出来了:深度优先搜索版SPFA。用DFS-SPFA去判断负权环即可。
【代码】
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define N 102
#define M 200002
using namespace std;int head[N],ver[M],nxt[M],edge[M],c;
int t,n,m,i,cnt[N],dis[N];
bool e[N],vis[N],in[N];
queue<int> q;
int read()
{
char c=getchar();
int w=,f=;
while(c<''||c>''){
if(c=='-') f=-;
c=getchar();
}
while(c<=''&&c>=''){
w=w*+c-'';
c=getchar();
}
return w*f;
}
void insert(int x,int y,int z)
{
c++;
ver[c]=y;
edge[c]=z;
nxt[c]=head[x];
head[x]=c;
}
bool dfs_SPFA(int x,int s)
{
vis[x]=;
for(int i=head[x];i;i=nxt[i]){
int y=ver[i];
if(dis[y]>dis[x]+edge[i]+s&&e[y]){
if(vis[y]) return ;
dis[y]=dis[x]+edge[i]+s;
if(dfs_SPFA(y,s)) return ;
}
}
vis[x]=;
return ;
}
void SPFA(int s)
{
memset(dis,0x3f,sizeof(dis));
memset(in,,sizeof(in));
q.push();
in[]=;
dis[]=;
while(!q.empty()){
int x=q.front();
q.pop();
for(int i=head[x];i;i=nxt[i]){
int y=ver[i];
if(dis[x]+edge[i]+s<dis[y]&&e[y]){
dis[y]=dis[x]+edge[i]+s;
if(!in[y]){
in[y]=;
q.push(y);
}
}
}
in[x]=;
}
}
void dfs(int x)
{
vis[x]=;
for(int i=head[x];i;i=nxt[i]){
int y=ver[i];
if(!vis[y]) dfs(y);
}
}
bool check(int x)
{
for(int i=;i<=n;i++){
if(e[i]){
memset(dis,0x3f,sizeof(dis));
memset(vis,,sizeof(vis));
if(dfs_SPFA(i,x)) return ;
}
}
SPFA(x);
if(dis[n]>=) return ;
return ;
}
int main()
{
freopen("earth.in","r",stdin);
freopen("earth.out","w",stdout);
cin>>t;
while(t--){
memset(e,,sizeof(e));
memset(head,,sizeof(head));
memset(vis,,sizeof(vis));
c=;
n=read();
m=read();
for(i=;i<=m;i++){
int u,v,w;
u=read();
v=read();
w=read();
insert(u,v,w);
}
dfs();
for(i=;i<=n;i++){
if(!vis[i]) e[i]=;
}
for(i=;i<=n;i++){
if(e[i]){
memset(vis,,sizeof(vis));
dfs(i);
if(!vis[n]) e[i]=;
}
}
int l=-,r=,mid,ans;
while(l<=r){
mid=(l+r)/;
if(check(mid)){
ans=dis[n];
r=mid-;
}
else l=mid+;
}
if(ans>1e9) cout<<"-1"<<endl;
else cout<<ans<<endl;
}
fclose(stdin);
fclose(stdout);
return ;
}
NOIP模拟赛(by hzwer) T3 小奇回地球的更多相关文章
- 2.17NOIP模拟赛(by hzwer) T3 小奇回地球
[题目背景] 开学了,小奇在回地球的路上,遇到了一个棘手的问题. [问题描述] 简单来说,它要从标号为 1 的星球到标号为 n 的星球,某一些星球之间有航线. 由于超时空隧道的存在,从一个星球到另一个 ...
- NOIP模拟赛(by hzwer) T2 小奇的序列
[题目背景] 小奇总是在数学课上思考奇怪的问题. [问题描述] 给定一个长度为 n 的数列,以及 m 次询问,每次给出三个数 l,r 和 P, 询问 (a[l'] + a[l'+1] + ... + ...
- NOIP模拟赛(by hzwer) T1 小奇挖矿
[题目背景] 小奇要开采一些矿物,它驾驶着一台带有钻头(初始能力值 w)的飞船,按既定 路线依次飞过喵星系的 n 个星球. [问题描述] 星球分为 2 类:资源型和维修型. 1. 资源型:含矿物质量 ...
- 2.17NOIP模拟赛(by hzwer) T2 小奇的序列
[题目背景] 小奇总是在数学课上思考奇怪的问题. [问题描述] 给定一个长度为 n 的数列,以及 m 次询问,每次给出三个数 l,r 和 P, 询问 (a[l'] + a[l'+1] + ... + ...
- 2.17NOIP模拟赛(by hzwer) T1 小奇挖矿
[题目背景] 小奇要开采一些矿物,它驾驶着一台带有钻头(初始能力值 w)的飞船,按既定 路线依次飞过喵星系的 n 个星球. [问题描述] 星球分为 2 类:资源型和维修型. 1. 资源型:含矿物质量 ...
- NOIP模拟赛 经营与开发 小奇挖矿
[题目描述] 4X概念体系,是指在PC战略游戏中一种相当普及和成熟的系统概念,得名自4个同样以“EX”为开头的英语单词. eXplore(探索) eXpand(拓张与发展) eXploit(经营与开发 ...
- NOIP模拟赛 by hzwer
2015年10月04日NOIP模拟赛 by hzwer (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...
- 2015-9-13 NOIP模拟赛 by hzwer
好老的题了,但是还是很有做头的. 总结 不吸氧看来确实是没法用stl的啊(set常数太大了,开O2也没过) SPFA没认真学,觉得有堆优化Dijkstra就天下无敌了,今天负边权教我做人 于是苦逼的只 ...
- 2015-9-13 NOIP模拟赛解题报告(by hzwer)
小奇挖矿 「题目背景」 小奇要开采一些矿物,它驾驶着一台带有钻头(初始能力值w)的飞船,按既定路线依次飞过喵星系的n个星球. 「问题描述」 星球分为2类:资源型和维修型. 1.资源型:含矿物质量a[i ...
随机推荐
- 配置Log4j(很详细)【转】
来自: http://www.blogjava.net/zJun/archive/2006/06/28/55511.html Log4J的配置文件(Configuration File)就是用来设置记 ...
- Stream之filter、distinct、skip、map、flatMap、match、find、reduce
一.Stream之filter.distinct.skip: package com.cy.java8; import java.util.Arrays; import java.util.List; ...
- windows 10 取消alt+tab的预览功能
1.win+r 输入regedit打开注册表编辑器 2.HKEY_CURRENT_USER/SOFTWARE/Microsoft/Windows/CurrentVersion/Explorer 3. ...
- keepalive + nginx 搭建高可用集群动态网站
环境准备: 两台节点部署keepalived,并且设为互为主从,实现高可用. 两台从节点部署nginx以及相关组件,作为真实服务器实现动态网站上线. 一.MASTER(BACKUP)节点下载keepa ...
- 基于原生XMLHttpRequest封装
用了一段时间的Ajax,感觉有很多的不足之处,于是就封装原生了 XMLHttpRequest . 废话不多说,直接上代码. var http = function () { 'use strict'; ...
- 【Linux 应用编程】基础知识
错误提示 Linux 提供的系统调用API,通常会在失败的时候返回 -1.如果想获取更多更详细的报错信息,需要借助全局变量 errno 和 perror 函数: #include <stdio. ...
- js中 json对象的转化 JSON.parse()
JSON.parse() 方法用来解析JSON字符串,json.parse()将字符串转成json对象.构造由字符串描述的JavaScript值或对象.提供可选的reviver函数用以在返回之前对所得 ...
- 分享一个linux系统中采用嵌套for循环比较两个数组内容,并输出相同值的shell脚本
#!/bin/bash array1=(1 3 5 6 7 9) array2=(3 4 9) echo array1=${array1[@]} echo array2=${array2[@]} fo ...
- CentOS7linux通过http配置共享自动创建yum源的shell脚本
因工作需要用到,所以记录一下配置流程 环境介绍: 两台CentOS7系统 yum源服务主节点IP:192.168.1.78 从节点IP:192.168.1.79(79从78上获取yum源) 配置78节 ...
- 《剑指offer》面试题26 复杂链表的复制 Java版
(定义一个新的数据结构,每个节点除了具有普通链表的next域外,还有一个额外的引用指向任意节点.我们要对由该特殊数据结构形成的链表进行复制.) 我的方法:也就是克隆一个这种特殊链表,很快想到先不考虑原 ...