题目链接:点击查看

题目大意:给出n个城市,每个城市都有一个拥挤度,从a到b的时间是(b的拥挤度-a的拥挤度)^3,点1为起点,求最短时间

题目分析:这个题第一感觉是个裸题,n还非常小,偷了个懒上了一发floyd,果不其然的WA了,回头去检查代码发现没有什么问题,去查了题解才知道原来是漏了一个很重要的细节,就是在处理边权上,(b的拥挤度-a的拥挤度)^3可能会出现负值,这样就会导致负环的出现,而一旦存在负环,则负环上的所有点都不可能存在最短路的,所以最后判断条件只要是最短路小于3或等于inf或位于负环上都输出问号,其他情况输出最小值即可。

这里放上两个代码,都是从网上新学的如何标记负环,以前都是用spfa判断负环,这个题要求的是标记负环,算是一个小变形吧

代码1:用cnt数组维护入队次数:

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<sstream>
#include<cmath>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=210;int n;struct Node
{int w,to;Node(int TO,int W){to=TO;w=W;}
};vector<Node>node[N];int maze[N][N];int a[N];int d[N];bool vis[N];int cnt[N];int dist(int i,int j)
{return (a[j]-a[i])*(a[j]-a[i])*(a[j]-a[i]);
}void spfa()
{memset(vis,false,sizeof(vis));memset(d,inf,sizeof(d));memset(cnt,0,sizeof(cnt));d[1]=0;vis[1]=true;queue<int>q;cnt[1]++;q.push(1);while(!q.empty()){int tem=q.front();q.pop();vis[tem]=false;for(int i=0;i<node[tem].size();i++){Node temp=node[tem][i];if(d[temp.to]>d[tem]+temp.w){d[temp.to]=d[tem]+temp.w;if(!vis[temp.to]&&cnt[temp.to]<=n-1)//标记所有负环上的点 {vis[temp.to]=true;q.push(temp.to);cnt[temp.to]++;}}}}
}int main()
{
//  freopen("input.txt","r",stdin);int w;cin>>w;int kase=0;while(w--){scanf("%d",&n);for(int i=1;i<=n;i++){node[i].clear();scanf("%d",a+i);}int m;scanf("%d",&m);for(int i=1;i<=m;i++){int a,b;scanf("%d%d",&a,&b);int dd=dist(a,b);node[a].push_back(Node(b,dd));}spfa(); int q;scanf("%d",&q);printf("Case %d:\n",++kase);while(q--){int p;scanf("%d",&p);if(d[p]<3||d[p]==inf||cnt[p]>=n-1)//注意这里的判断条件cout<<"?"<<endl;elsecout<<d[p]<<endl;}}return 0;
}

代码2:用book数组标记负环上的点(用dfs搜索所有负环可到达的点:

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<sstream>
#include<cmath>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=210;int n;struct Node
{int w,to;Node(int TO,int W){to=TO;w=W;}
};vector<Node>node[N];int maze[N][N];int a[N];int d[N];bool vis[N];int cnt[N];bool book[N];int dist(int i,int j)
{return (a[j]-a[i])*(a[j]-a[i])*(a[j]-a[i]);
}void dfs(int u)
{book[u]=true;for(int i=0;i<node[u].size();i++){if(!book[node[u][i].to])dfs(node[u][i].to);}
}void spfa()
{memset(vis,false,sizeof(vis));memset(d,inf,sizeof(d));memset(cnt,0,sizeof(cnt));memset(book,false,sizeof(book));d[1]=0;vis[1]=true;queue<int>q;cnt[1]++;q.push(1);while(!q.empty()){int tem=q.front();q.pop();vis[tem]=false;for(int i=0;i<node[tem].size();i++){Node temp=node[tem][i];if(d[temp.to]>d[tem]+temp.w){d[temp.to]=d[tem]+temp.w;if(!vis[temp.to])//标记所有负环上的点 {vis[temp.to]=true;q.push(temp.to);cnt[temp.to]++;if(cnt[temp.to]>n-1){dfs(temp.to);//搜索所有与该点相连的点,并做好标记return;}}}}}
}int main()
{
//  freopen("input.txt","r",stdin);int w;cin>>w;int kase=0;while(w--){scanf("%d",&n);for(int i=1;i<=n;i++){node[i].clear();scanf("%d",a+i);}int m;scanf("%d",&m);for(int i=1;i<=m;i++){int a,b;scanf("%d%d",&a,&b);int dd=dist(a,b);node[a].push_back(Node(b,dd));}spfa(); int q;scanf("%d",&q);printf("Case %d:\n",++kase);while(q--){int p;scanf("%d",&p);if(d[p]<3||d[p]==inf||book[p])//注意这里的判断条件cout<<"?"<<endl;elsecout<<d[p]<<endl;}}return 0;
}

LightOJ - 1074 Extended Traffic(最短路+判断负环)相关推荐

  1. LightOJ 1074 Extended Traffic(spfa+dfs标记负环上的点)

    题目链接:https://cn.vjudge.net/contest/189021#problem/O 题目大意:有n个站点,每个站点都有一个busyness,从站点A到站点B的花费为(busynes ...

  2. POJ - 3259 Wormholes(判断负环)

    题目链接:点击查看 题意:最短路判断负环 这里介绍三种方法判断负环,分别是spfa,bellman-ford和flyod算法,不过spfa的速度能比bellman-ford的速度慢了接近20倍是出乎 ...

  3. POJ 3259 Wormholes【最短路/SPFA判断负环模板】

    农夫约翰在探索他的许多农场,发现了一些惊人的虫洞.虫洞是很奇特的,因为它是一个单向通道,可让你进入虫洞的前达到目的地!他的N(1≤N≤500)个农场被编号为1..N,之间有M(1≤M≤2500)条路径 ...

  4. 模板 - 判断负环(超时高效优化技巧)、01分数规划

    整理的算法模板合集: ACM模板 判断负环 判正环求最长路,判负环求最短路 int n; // 总点数 int h[N], w[N], e[N], ne[N], idx; // 邻接表存储所有边 in ...

  5. UVA 558 SPFA 判断负环

    这个承认自己没看懂题目,一开始以为题意是形成环路之后走一圈不会产生负值就输出,原来就是判断负环,用SPFA很好用,运用队列,在判断负环的时候,用一个数组专门保存某个点的访问次数,超过了N次即可断定有负 ...

  6. 负环——spfa判断负环的两种方式

    第一种:(不推荐) 统计每个点的入队次数,如果某一个点入队了n次,则说明存在负环. 第二种: 统计当前每个点的最短路的边数,如果存在负环,负环上的某一个点的最短路边数一定会是正无穷,只要边数超过n(节 ...

  7. spfa 判断负环 (转载)

    当然,对于Spfa判负环,实际上还有优化:就是把判断单个点的入队次数大于n改为:如果总的点入队次数大于所有点两倍 时有负环,或者单个点的入队次数大于sqrt(点数)有负环.这样时间复杂度就降了很多了. ...

  8. Wormholes——Bellman-Ford判断负环

    [题目描述] While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A w ...

  9. POJ3259(Wormholes) 判断负环

    题意: 农夫john发现了一些虫洞,虫洞是一种在你到达虫洞之前把你送回目的地的一种方式,FJ的每个农场,由n块土地(编号为1-n),M 条路,和W个 虫洞组成,FJ想从一块土地开始,经过若干条路和虫洞 ...

最新文章

  1. 行业观察 | 全球IoT云平台第一股诞生,IoT离爆发还有多远?
  2. js关闭窗口无提示,不支持FF
  3. Java黑皮书课后题第6章:*6.2(求一个整数各位数字之和)编写一个方法,计算一个整数各位数字之和。使用下面的方法头:public static int sumDigits(long n)
  4. 如何使用busybox编译和生成最简linux根文件系统(rootfs)
  5. 任务完成:我从CNC2018 GetAJob挑战中学到的东西
  6. 作为一名通信老司机,我是如何看待翼龙通信无人机救灾的?
  7. 头条面试题,4种解法,60+图清晰讲解,面试官让我优化,小夕一通优化最终击败100%用户
  8. 前端开发之功能封装大全
  9. C语言判断逆反素数,判断素数的几种方法思考[C语言]
  10. Kubernetes 集群安全 - 鉴权 实战rolebinding和clusterrole
  11. 求平方根java实现
  12. shopex php5.3,shopex.4.85支持php5.3 | 学步园
  13. zabbix 监控81端口
  14. 蓝鲸作业流程编排--参数使用
  15. 学以致用——Java源码——使用Graphics2D类draw方法绘制立方体(Drawing Cubes)
  16. AE效果:杂色和颗粒
  17. debian中文输入法——拼音和五笔的解决方法
  18. 语音识别技术基础理解
  19. 【软件测试】测试大纲编写模板范文
  20. ffmpeg学习笔记

热门文章

  1. SpringSecurity常用过滤器介绍
  2. Nginx server_name精确匹配配置
  3. 为什么需要Survivor区?只有Eden不行吗?
  4. 什么是控制反转(IOC)?什么是依赖注入?
  5. 数据库压力变大,读写分离吧
  6. Spring新注解详解
  7. 选择结构_标准的switch语句
  8. 单例设计模式-饿汉式
  9. 开闭原则coding
  10. 千鸟弹幕机器人_千鸟熊猫TV直播弹幕机器人软件