T1

T2

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

数据随机和构造结合生成

这题的题意好含糊。。理解错了好多次。。理解错了就不会做了(迷之微笑)

题意:给定一个有向图,每条边有一个权值,可以给所有边加或减同一个值k(k为整数),使得1到n的最短路存在,最短路>=0且尽量小。

正确理解:

如果1到n的路径中有负环,那最短路就不存在;

如果1到n的最短路是负数,那也不满足题意。

题解:

我们可以发现k具有单调性:如果+k都还存在负环or最短路为负,那比k小的更加不满足题意;反之,比k大的必定满足题意。

二分k,spfa判断图中是否有负环、并求出最短路,判断是否满足题意。

注意:判断负环前应删去那些与起点、终点不是都联通的点!

比如这种情况,图中存在负环,但是与1到n的最短路无关,错误输出为105,正确输出为5。

优化:用spfa判断负环的方法

判断给定的有向图中是否存在负环。

      利用 spfa 算法判断负环有两种方法:

      1) spfa 的 dfs 形式,判断条件是存在一点在一条路径上出现多次。

      2) spfa 的 bfs 形式,判断条件是存在一点入队次数大于总顶点数。

SPFA的两种写法,bfs和dfs,bfs判别负环不稳定,相当于限深度搜索,但是设置得好的话还是没问题的,dfs的话判断负环很快。

我原本的方法是在bfs里加一个数组,记录每个点入队了多少次,如果有一个点入队次数大于n则有负环。

时间是这样的:

改成dfs:

改成dfs这里调了挺久的。但是的确快了很多。

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std; const int N=,Inf=(int)1e9;
struct node{
int x,y,d,next;
}a[N*N];
int n,m,len,dis[N],first[N];
bool in[N],can[N],vis[N];
queue<int> q; int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
} void ins(int x,int y,int d)
{
len++;
a[len].x=x;a[len].y=y;a[len].d=d;
a[len].next=first[x];first[x]=len;
} int minn(int x,int y){return x<y ? x:y;} void dfs(int x)
{
vis[x]=;
for(int i=first[x];i;i=a[i].next)
if(!vis[a[i].y]) dfs(a[i].y);
} bool dfs_spfa(int x,int ad)
{
in[x]=;
for(int i=first[x];i;i=a[i].next)
{
int y=a[i].y;
if(dis[y]>dis[x]+a[i].d+ad && can[y])
{
if(in[y]) return ;//负边成环
dis[y]=dis[x]+a[i].d+ad;//虽然dis[x]=dis[y]=0,但如果是负边,a[i].d+ad<0
if(dfs_spfa(y,ad)) return ;
}
}
in[x]=;
return ;
} void bfs_spfa(int ad)
{
while(!q.empty()) q.pop();
memset(dis,,sizeof(dis));
memset(in,,sizeof(in));
q.push();dis[]=;in[]=;
while(!q.empty())
{
int x=q.front();in[x]=;q.pop();
for(int i=first[x];i;i=a[i].next)
{
int y=a[i].y;
int d=a[i].d+ad;
if(dis[y]>dis[x]+d && can[y])
{
dis[y]=dis[x]+d;
if(!in[y]) in[y]=,q.push(y);
}
}
}
} bool judge(int ad)
{
// 判断是否有负环
for(int i=;i<=n;i++)
if(can[i])
{
memset(dis,,sizeof(dis));//不用算具体数值,只要求到有负环即可。
memset(in,,sizeof(in));
if(dfs_spfa(i,ad)) return ;//dfs_spfa(i)相当于找i这个点是不是在一个负环中,所以要每个点都做一遍,不是在负环中很快就会跳出,否则就遍历一遍负环。
}
//屏蔽了的这种方法理论上也可以,但是相当于用dfs做了一遍spfa,比bfs更慢,超时。
/* memset(dis,63,sizeof(dis));dis[1]=0;
memset(in,0,sizeof(in));
if(can[1]==0) return 0;
if(can[1]==1 && dfs_spfa(1,ad)) return 0;*/
//跑最短路
bfs_spfa(ad);
if(dis[n]>= && dis[n]<=Inf) return ;
return ;
} int main()
{
// freopen("a.in","r",stdin);
freopen("earth.in","r",stdin);
freopen("earth.out","w",stdout);
int T;
scanf("%d",&T);
while(T--)
{
len=;
memset(first,,sizeof(first));
n=read(),m=read();
int mn=;
for(int i=;i<=m;i++)
{
int x=read(),y=read(),d=read();
ins(x,y,d);
}
memset(vis,,sizeof(vis));
dfs();
for(int i=;i<=n;i++)
{
if(vis[i]) can[i]=;
else can[i]=;
//can[x]=1 x点与起点联通
}
for(int i=;i<=n;i++)
{
if(can[i])
{
memset(vis,,sizeof(vis));
dfs(i);
if(!vis[n]) can[i]=;
}
}//can[x]=1 x点与起点、终点都联通
int l=-,r=,ans=-;
while(l<=r)//二分加或减多少
{
int mid=(l+r)>>;
if(judge(mid)) ans=dis[n],r=mid-;
else l=mid+;
// printf("l = %d r = %d\n",l,r);
}
printf("%d\n",ans);
}
return ;
}

最新文章

  1. [osx] android studio下修改avd的hosts文件
  2. jquery的checkbox 全选和全不选
  3. 开启Ubuntu root 远程登录
  4. List多对多的查询应用
  5. 在Navicat for MySQL中打开视图时,提示视图没有主键的问题
  6. iOS开发之UITextView,设置textView的行间距及placeholder
  7. object-c学习笔记
  8. 仿word导航窗口的展开与折叠
  9. IoGetDeviceObjectPointer .
  10. oracle 中控制文件中到底记录了哪些信息
  11. codeforces C. Devu and Partitioning of the Array
  12. 1218.3——init自定义
  13. 解决升级Xcode后插件不能使用的问题
  14. delete、truncate与drop的区别
  15. 聚币网API[Python2版]
  16. requests.post发送字典套字典
  17. UNIX网络编程——客户/服务器程序设计示范(总结)
  18. Spring Boot 2.0.1 入门教程
  19. go [第一篇]初识
  20. Alpha 冲刺 (7/10)

热门文章

  1. 安装Sql Server 2008的时候报错说找不到某个安装文件
  2. Unity3d工具方法小集
  3. 玩转VIM之将Vim全副武装
  4. vue2.0 $emit $on组件通信
  5. 「个人训练」Can you solve this equation?(HDU-2199)
  6. resetroot_169route_python2(用于ubuntu12.04和14.04,centos系列)
  7. 关键词提取TF-IDF算法/关键字提取之TF-IDF算法
  8. CentOS 6.5 下安装redis
  9. [leetcode-609-Find Duplicate File in System]
  10. C - 最长公共子序列