Description

While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way path that delivers you to its destination at a time that is BEFORE you entered the wormhole! Each of FJ's farms comprises N (1 ≤ N ≤ 500) fields conveniently numbered 1..NM (1 ≤ M ≤ 2500) paths, and W (1 ≤ W ≤ 200) wormholes.

As FJ is an avid time-traveling fan, he wants to do the following: start at some field, travel through some paths and wormholes, and return to the starting field a time before his initial departure. Perhaps he will be able to meet himself :) .

To help FJ find out whether this is possible or not, he will supply you with complete maps to F (1 ≤ F ≤ 5) of his farms. No paths will take longer than 10,000 seconds to travel and no wormhole can bring FJ back in time by more than 10,000 seconds.

Input

Line 1: A single integer, FF farm descriptions follow.  Line 1 of each farm: Three space-separated integers respectively: NM, and W  Lines 2.. M+1 of each farm: Three space-separated numbers ( SET) that describe, respectively: a bidirectional path between S and E that requires T seconds to traverse. Two fields might be connected by more than one path.  Lines M+2.. MW+1 of each farm: Three space-separated numbers ( SET) that describe, respectively: A one way path from S to E that also moves the traveler back T seconds.

Output

Lines 1.. F: For each farm, output "YES" if FJ can achieve his goal, otherwise output "NO" (do not include the quotes).

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.
题目意思:对于t组输入输出,有N个点,M条双向通路,K个虫洞。虫洞是一个单向的通路。问能否从某一个点出发,通过一些路径和虫洞,返回到出发点,并且时间还要早于出发时间,这样他就能够遇到他自己了。
解题思路:又是John,想都不用想又是USACO的题,美国果然是农业立国啊。在第二组样例中,John沿着1->2->3->1,从第一个点出发回到第一个点,所需时间为-1,这样他就能够遇到自己了。这该怎么思考?遇到虫洞会回到过去,时间回溯。实际上就是要求判断一个带有负权的有向网中是否存在负权值回路,
我们知道可以使用Bellman-Ford可以判断是否存在负环,因为出现了负值回路后会不断的松弛。这里我们用优化后的SPFA来实现。
原理:如果存在负权值回路,那么从源点到某一个点的最短路径可以无限缩短,某些顶点入队列将会超过N次(N为顶点个数)。
ps:代码有给出了另外一种判断是否有负环的方法,时间会更快。从任意一点出发求最短路,必定会求出到其他所有点的最短路,若其中某个点在一个负权回路中,那么它肯定会不断地走这个回路以使到这个点的花费越小越好,这时候该点到出发点的距离就会为负值,所以只需从一个点开始便能找到是否存在负回路,这里我们就只看从源点到源点的dis就可以了。
 
 #include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define INF 0x3f3f3f3f
#define maxs 10010
using namespace std;
struct node
{
int to;
int w;
} t;
vector<node>Map[maxs];
int dis[maxs];
int vis[maxs];
int n,m,k;
void add(int s,int e,int w)
{
t.to=e;
t.w=w;
Map[s].push_back(t);
}
void init()
{
int i;
memset(dis,INF,sizeof(dis));
memset(vis,,sizeof(vis));
for(i=; i<=n; i++)
{
Map[i].clear();
}
}
int SPFA(int s)
{
int cnt[maxs]= {};///记录每个点入队次数
int i;
dis[s]=;
vis[s]=;
queue<int>q;
q.push(s);
cnt[s]++;
while(!q.empty())
{
int u=q.front();
/*if(cnt[u]>=n)
{
return 0;///这里用来判断入队列是否超过N次
}*/
q.pop();
vis[u]=;
for(i=; i<Map[u].size(); i++)
{
int to=Map[u][i].to;
if(dis[to]>dis[u]+Map[u][i].w)
{
dis[to]=dis[u]+Map[u][i].w;///松弛操作
if(dis[]<)///这种判断是否有负环的更快。如果起始点的dis[s]<0说明存在负环
{
return ;
}
if(!vis[to])
{
vis[to]=;
q.push(to);
cnt[to]++;
}
}
}
}
return ;
}
int main()
{
int t,i,j,u,v,w;
scanf("%d",&t);
for(i=; i<=t; i++)
{
scanf("%d%d%d",&n,&m,&k);
init();
while(m--)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
while(k--)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,-w);///虫洞时间取负值
}
if(SPFA())
{
printf("NO\n");
}
else
{
printf("YES\n");
}
}
return ;
}

这里再附上使用邻接矩阵和Bellman-Ford算法的代码。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
struct Edge
{
int f;///起点
int t;///终点
int c;///距离
} edge[];
int dist[];
int n,m,h,cnt;
int bellman_ford()
{
memset(dist,inf,sizeof(dist));
dist[]=;///起点
int i,j;
for(j=; j<=n; j++)
{
for(i=; i<=cnt; i++)
{
if(dist[edge[i].t]>dist[edge[i].f]+edge[i].c)///松弛操作
{
dist[edge[i].t]=dist[edge[i].f]+edge[i].c;
}
}
}
int flag=;
for(i=; i<=cnt; i++)///遍历所有的边
{
if(dist[edge[i].t]>dist[edge[i].f]+edge[i].c)
{
flag=;///存在从源点可达的负权回路
break;
}
}
return flag;
}
int main()
{
int i,t;
scanf("%d",&t);
while(t--)
{
cnt=;
scanf("%d %d %d",&n,&m,&h);
int u,v,w;
for(i=; i<=m; i++)
{
cnt++;
scanf("%d %d %d",&u,&v,&w);
edge[cnt].f=u;
edge[cnt].t=v;
edge[cnt].c=w;
cnt++;
edge[cnt].f=v;
edge[cnt].t=u;
edge[cnt].c=w;
}
for(i=; i<=h; i++)
{
cnt++;
scanf("%d %d %d",&u,&v,&w);
edge[cnt].f=u;
edge[cnt].t=v;
edge[cnt].c=-w;
}
if(bellman_ford())
printf("NO\n");
else
printf("YES\n");
}
return ;
}
 

Wormholes POJ 3259(SPFA判负环)的更多相关文章

  1. Wormholes POJ - 3259 spfa判断负环

    //判断负环 dist初始化为正无穷 //正环 负无穷 #include<iostream> #include<cstring> #include<queue> # ...

  2. bzoj 1715: [Usaco2006 Dec]Wormholes 虫洞【spfa判负环】

    tag是假的,用了及其诡异的方法判负环 正权无向边和负权有向边的图 #include<iostream> #include<cstdio> #include<cstrin ...

  3. POJ - 3851-Wormholes(SPFA判负环)

    A friend of yours, an inventor, has built a spaceship recently and wants to explore space with it. D ...

  4. POJ 3259 Wormholes(SPFA判负环)

    题目链接:http://poj.org/problem?id=3259 题目大意是给你n个点,m条双向边,w条负权单向边.问你是否有负环(虫洞). 这个就是spfa判负环的模版题,中间的cnt数组就是 ...

  5. Poj 3259 Wormholes(spfa判负环)

    Wormholes Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 42366 Accepted: 15560 传送门 Descr ...

  6. poj 2049(二分+spfa判负环)

    poj 2049(二分+spfa判负环) 给你一堆字符串,若字符串x的后两个字符和y的前两个字符相连,那么x可向y连边.问字符串环的平均最小值是多少.1 ≤ n ≤ 100000,有多组数据. 首先根 ...

  7. poj 1364 King(线性差分约束+超级源点+spfa判负环)

    King Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 14791   Accepted: 5226 Description ...

  8. BZOJ 1715: [Usaco2006 Dec]Wormholes 虫洞 DFS版SPFA判负环

    Description John在他的农场中闲逛时发现了许多虫洞.虫洞可以看作一条十分奇特的有向边,并可以使你返回到过去的一个时刻(相对你进入虫洞之前).John的每个农场有M条小路(无向边)连接着N ...

  9. spfa判负环

    bfs版spfa void spfa(){ queue<int> q; ;i<=n;i++) dis[i]=inf; q.push();dis[]=;vis[]=; while(!q ...

  10. 2018.09.24 bzoj1486: [HNOI2009]最小圈(01分数规划+spfa判负环)

    传送门 答案只保留了6位小数WA了两次233. 这就是一个简单的01分数规划. 直接二分答案,根据图中有没有负环存在进行调整. 注意二分边界. 另外dfs版spfa判负环真心快很多. 代码: #inc ...

随机推荐

  1. archLinux 学习笔记--mlocate的安装与使用

    locate - 查找文件的简单方法 locate 程序会执行一次快速的路径名数据库搜索,并且输出每个与给定子字符串相匹配的路径名. 使用时却发现archlinux出现 bash: locate:未找 ...

  2. 移动端触摸滑动插件Swiper使用指南

    Swiper是一款开源.免费.功能十分强大的移动端内容触摸滑动插件,目前的最新版本是Swiper4.Swiper主要面向的是手机.平板电脑等移动设备,帮助开发者轻松实现触屏焦点图.触屏Tab切换.触屏 ...

  3. jquery里遍历普通数组和多维数组的方法及实例

    jquery里遍历数组用的是$.each,下面站长给大家几个具体的实例: 实例1.遍历一个普通的一维数组: 1 2 3 4 5 6 7 8 <script> //声明数据有下面两种方式 / ...

  4. es6之扩展运算符 三个点(...)

    对象的扩展运算符理解对象的扩展运算符其实很简单,只要记住一句话就可以: 对象中的扩展运算符(...)用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中 let bar = { a: 1, b: 2 ...

  5. ARMCC中$Super$$和$Sub$$的使用

    代码: extern int $Super$$main(void); /* re-define main function */ int $Sub$$main(void) { rt_hw_interr ...

  6. Dbshop v1.3任意用户密码重置漏洞

    0x00 前言 年也过的差不多了,各自也都回到岗位忙碌起来了,新的一年祝大家诸事顺利,洞洞高危!好了进入正题 0x01 漏洞简介 本次主要写个简单的逻辑漏洞!然后抛个Message 内置高危. 1.找 ...

  7. vue中-webkit-box-orient:vertical打包放到线上不显示

    解决方法: 1.找到build文件夹 下的webpack.prod.conf.js文件 2.注释new OptimizeCSSPlugin({                          css ...

  8. FPGA千兆网UDP协议实现

    接着上一篇百兆网接口的设计与使用,我们接着来进行FPGA百兆网UDP(User Datagram Protocol)协议的设计. 1)UDP简介 在此,参考博主夜雨翛然的博文“https://www. ...

  9. 20155210潘滢昊 2016-2017-2《Java程序设计》第一周学习总结

    20155210 2016-2017-2<Java程序设计>第一周学习总结 教材学习内容总结 1.1.1: 本节主要讲了Java的由来,1995年5月23日是Java公认的诞生日.还有版本 ...

  10. C语言 迭代部分的代码编写

    C语言代码学习 迭代部分 迭代要用到函数部分的知识,一开始我写了计算n!的计算,代码和运行结果如下: 结果只能单一的计算出整数内的值,如果输入负值则结果为返回值1,显然是不对的,根据查书学习以后,知道 ...