农夫约翰在探索他的许多农场,发现了一些惊人的虫洞。虫洞是很奇特的,因为它是一个单向通道,可让你进入虫洞的前达到目的地!他的N(1≤N≤500)个农场被编号为1..N,之间有M(1≤M≤2500)条路径,W(1≤W≤200)个虫洞。FJ作为一个狂热的时间旅行的爱好者,他要做到以下几点:开始在一个区域,通过一些路径和虫洞旅行,他要回到最开时出发的那个区域出发前的时间。也许他就能遇到自己了:)。为了帮助FJ找出这是否是可以或不可以,他会为你提供F个农场的完整的映射到(1≤F≤5)。所有的路径所花时间都不大于10000秒,所有的虫洞都不大于万秒的时间回溯。Input第1行:一个整数F表示接下来会有F个农场说明。 每个农场第一行:分别是三个空格隔开的整数:N,M和W 第2行到M+1行:三个空格分开的数字(S,E,T)描述,分别为:需要T秒走过S和E之间的双向路径。两个区域可能由一个以上的路径来连接。 第M +2到M+ W+1行:三个空格分开的数字(S,E,T)描述虫洞,描述单向路径,S到E且回溯T秒。OutputF行,每行代表一个农场 每个农场单独的一行,” YES”表示能满足要求,”NO”表示不能满足要求。Sample Input

2
3 3 1
1 2 2
1 3 4
2 3 1
3 1 3
3 2 1
1 2 3
2 3 4
3 1 8

Sample Output

NO
YES

Hint

For farm 1, FJ cannot travel back in time. 
For farm 2, FJ could travel back in time by the cycle 1->2->3->1, arriving back at his starting location 1 second before he leaves. He could start from anywhere on the cycle to accomplish this.

#include<cstdio>
#include<string>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<map>
#include<cctype>
#include<stack>
#include<sstream>
#include<list>
#include<assert.h>
#include<bitset>
#include<numeric>
#define debug() puts("++++")
#define gcd(a,b) __gcd(a,b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a,b,sizeof(a))
#define sz size()
#define be begin()
#define mp make_pair
#define pu push_up
#define pd push_down
#define cl clear()
#define lowbit(x) -x&x
#define all 1,n,1
#define rep(i,x,n) for(int i=(x); i<=(n); i++)
#define in freopen("in.in","r",stdin)
#define out freopen("out.out","w",stdout)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> P;
const int INF = 0x3f3f3f3f;
const LL LNF = 1e18;
const int maxn = 1e5+20;
const int maxm = 1e6 + 10;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int dx[] = {-1,1,0,0,1,1,-1,-1};
const int dy[] = {0,0,1,-1,1,-1,1,-1};
int dir[4][2] = {{0,1},{0,-1},{-1,0},{1,0}};
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int tot,n,m,x,s;
int u,v,w;
int dis[maxn];
int cnt[maxn],vis[maxn];
struct cmp
{bool operator()(int a,int b){return dis[a] > dis[b];}
};int head[maxn];
struct node
{int v,w,nxt;
}e[maxn];
void init()
{tot=0;ms(cnt,0);ms(head,-1);ms(dis,INF);//求最长路径开始设为0ms(vis,0);
}
void add(int u,int v,int w)
{e[tot].v=v;e[tot].w=w;e[tot].nxt=head[u];head[u]=tot++;
}int spfa(int s)
{queue<int> q;vis[s]=1;dis[s]=0;cnt[s]++;q.push(s);while(!q.empty()){int u = q.front(); q.pop();vis[u]=0; //
        for(int i=head[u];i!=-1;i=e[i].nxt){int v = e[i].v;if(dis[v] > dis[u] + e[i].w){dis[v] = dis[u] + e[i].w;if(!vis[v]){vis[v]=1;q.push(v);if(++cnt[v]>n) return 1;//有负环
                }}}}return 0;
}int main()
{int t;scanf("%d",&t);while(t--){scanf("%d%d%d",&n,&m,&w);init();int a,b,c;for(int i=1;i<=m;i++){scanf("%d%d%d",&a,&b,&c);add(a,b,c);add(b,a,c);}for(int i=1;i<=w;i++){scanf("%d%d%d",&a,&b,&c);add(a,b,-c);}if(spfa(1)) puts("YES");else puts("NO");}
}
/*
【题意】【类型】
SPFA判断负环【分析】
spfa算法我们都知道spfa算法是对bellman算法的优化,那么如何用spfa算法来判断负权回路呢?我们考虑一个节点入队的条件是什么,只有那些在前一遍松弛中改变了距离估计值的点,才可能引起他们的邻接点的距离估计值的改变。因此,用一个先进先出的队列来存放被成功松弛的顶点。同样,我们有这样的定理:“两点间如果有最短路,那么每个结点最多经过一次。也就是说,这条路不超过n-1条边。”(如果一个结点经过了两次,那么我们走了一个圈。如果这个圈的权为正,显然不划算;如果是负圈,那么最短路不存在;如果是零圈,去掉不影响最优值)。也就是说,每个点最多入队n-1次(这里比较难理解,需要仔细体会,n-1只是一种最坏情况,实际中,这样会很大程度上影响程序的效率)。有了上面的基础,思路就很显然了,加开一个数组记录每个点入队的次数(num),然后,判断当前入队的点的入队次数,如果大于n-1,则说明存在负权回路。【时间复杂度&&优化】【trick】【数据】
*/

View Code

转载于:https://www.cnblogs.com/Roni-i/p/9446542.html

POJ 3259 Wormholes【最短路/SPFA判断负环模板】相关推荐

  1. UVA 558 SPFA 判断负环

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

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

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

  3. spfa 判断负环 (转载)

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

  4. 算法基础课-搜索与图论-spfa-AcWing 852. spfa判断负环:spfa求负环板子

    文章目录 题目分析 题目链接 题目分析 来源:acwing 分析: dist[x] 表示从源点到x点的最短距离. spfa算法求最短路的算法步骤: 初始化一个队列,将起点入队. 取出队头元素t,遍历它 ...

  5. POJ 3259 Wormholes(bellman_ford,判断有没有负环回路)

    题意:John的农场里field块地,path条路连接两块地,hole个虫洞,虫洞是一条单向路,不但会把你传送到目的地,而且时间会倒退Ts.我们的任务是知道会不会在从某块地出发后又回来,看到了离开之前 ...

  6. PKU3259-Wormholes(SPFA判断负环,含题意)

    题目: 一开始被题目的梦幻给弄的晕乎乎.的却,作者很会yy. 意思是: 一个农夫有cas个田地,然后每个田地里面有nodeNum个结点,结点之间可能有多条路径(这是一个无向图),田地里还有w个虫洞(虫 ...

  7. spfa判断负环( 负环判定 + spfa )

    给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环, 边权可能为负数. 请你求出 1 号点到 n 号点的最短距离,如果无法从 1 号点走到 n 号点,则输出 impossible. 数据保证 ...

  8. AcWing 852. spfa判断负环(spfa or bellman)

    题目链接 https://www.acwing.com/problem/content/description/854/ 思路 思路一 我们定义一个数组cnt,cnt[i]表示i这个点被更新的次数,那 ...

  9. 时光机 (spfa判断负环)

    cnt数组记录每个点入栈次数,无负环时最大入栈次数为n,因为最短路最多有n-1条边. 有负环时最短路趋于负无穷,入栈次数大于n. #include<stdio.h> #include< ...

最新文章

  1. IDEA插件推荐:中文字符自动转化!
  2. iBatis应用之获取表的元数据
  3. LDAP落地实战(三):GitLab集成OpenLDAP认证
  4. 好用的NSPredicate
  5. POJ 2251 Dungeon Master(三维BFS求最短路径)
  6. PyTorch 1.0 中文文档:Tensor(张量)的属性
  7. ALSA音频工具amixer,aplay,arecord
  8. distcp用于集群中数据传输解读
  9. javascript 开发多种类型的应用(Electron 跨平台开发)
  10. mongodb常用命令脚本化-自动化运维
  11. docker-将ab测试工具打包镜像
  12. 高中计算机会考基本知识点,高中计算机会考基本知识点
  13. wifi信号增强android,WiFi信号增强大师
  14. html好看css标题样式,比较好看的css 自定义样式(标题 h1 h2 h3)
  15. 【Windows批处理】批处理压缩包内加密pdf文件解密
  16. WeX5制作的app,界面模仿b站(哔哩哔哩弹幕视频网)客户端
  17. Azure NSG Flow Log 引发的自嗨 -- 日志 ETL 流式处理
  18. xv6 6.S081 Lab5: cow
  19. 电阻色环表_色环电阻识别方法
  20. python可视化小案例giao

热门文章

  1. (转)关于eclipse的TestNG的插件安装方法
  2. 史诗级pg脚本,亲测好使
  3. UIButton中的三个UIEdgeInsets属性
  4. 【Android】手机端的投射
  5. linux 使用退格键时出现^H解决方法
  6. android Ant批打包学习(零)--基础知识
  7. 软件定义闪存:加速闪存规模化应用
  8. 淘宝商品库MySQL优化实践的学习
  9. MOS2010的界面介绍和定制方法简介【资料汇集】
  10. 雪儿--北京欢迎你!!!