标签:spfa+邻接表判断负权
错误点:多组数据时没有对vector进行清空
Wormholes
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 71066 Accepted: 26409
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…N, M (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, F. F farm descriptions follow.
Line 1 of each farm: Three space-separated integers respectively: N, M, and W
Lines 2…M+1 of each farm: Three space-separated numbers (S, E, T) 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…M+W+1 of each farm: Three space-separated numbers (S, E, T) 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.
译文摘自https://blog.csdn.net/zitian246/article/details/76082393
t译文:农夫约翰在探索他的许多农场,发现了一些惊人的虫洞。虫洞是很奇特的,因为它是一个单向通道,可让你进入虫洞的前达到目的地!他的N(1≤N≤500)个农场被编号为1…N,之间有M(1≤M≤2500)条路径,W(1≤W≤200)个虫洞。作为一个狂热的时间旅行FJ的爱好者,他要做到以下几点:开始在一个区域,通过一些路径和虫洞旅行,他要回到最开时出发的那个区域出发前的时间。也许他就能遇到自己了:)。为了帮助FJ找出这是否是可以或不可以,他会为你提供F个农场的完整的映射到(1≤F≤5)。所有的路径所花时间都不大于10000秒,所有的虫洞都不大于万秒的时间回溯。
输入 第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秒。 输出 F行,每行代表一个农场 每个农场单独的一行,” YES”表示能满足要求,”NO”表示不能满足要求。 NO YES
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 1005;
const int INF = 0x3f3f3f3f; //无穷大
const int inf = 0x3f;
struct edge {
int e,w;//终点,边的值
edge(int _e,int _w) { //构造函数,使用edge(a,b) 可以直接构造一个e = a,w = b结构体
e = _e,w = _w;
}
//如果需要申请结构体变量,还需要加上下面这个构造函数
//edge(){};(对没错里面都是空的)
};
vector<edge> Map[maxn]; //邻接表存图
bool vis[maxn]; //该点是否在队列中
int dis[maxn]; //初始点到每点的最短距离
int cnt[maxn]; //该点用了几次,判断是否有负权,负环
int n;
int spfa(int a) {
memset(dis,inf,(n+1)<<2); //将数组中前n+1个数初始化为无穷大
memset(vis,0,sizeof(vis));
memset(cnt,0,sizeof(cnt));
dis[a] = 0;
vis[a] = true;
/*上面都是和Dijkstra一样的,接下来才是重头*/
/*Dijkstra:每次找权值最小的边,然后根据这个边所连的点更新dis数组
所以每n次操作只能找出一个点来
SPFA:如果该边可以松弛且连接的点未被使用,就把该边连接的那个点存进队列等待更新
所以每经过一个点就可以把该点所有边所连接的点(可以被松弛的)都记录然后更新
*/
queue<int>q;
q.push(a);
// printf("-------%d\n",a);
cnt[a]++;
while(!q.empty()) {
int buf = q.front(); //取出队首的点
q.pop();
vis[buf] = 0;
for(int i=0;i<Map[buf].size();i++)
{
int p = Map[buf][i].e; //取出队首的点
int w = Map[buf][i].w;
if(dis[buf]+w < dis[p])
{ //如果可以松弛就更新dis数组,此处和Dijkstra一样
dis[p] = dis[buf]+w; //松弛的同时如果该点未被访问就把该点扔进队列
if(!vis[p]) { //不同的地方,如果p点未被使用,则将其放入队列(也就是p点可以被松弛)
cnt[p]++;
// printf("------%d\n",p);
if(cnt[p]>n)
return 1;
q.push(p);
vis[p] = 1;
}
}
}
}
// for(int i=1;i<=n;i++)
// {
// printf("%d--%d\n",i,cnt[i]);
// }
return 0;
}
int main()
{
int f,m,w,s,e,t,i,j;
scanf("%d",&f);
while(f--)
{
memset(Map,0,sizeof(Map));
scanf("%d%d%d",&n,&m,&w);
//输入路径
for(i=0;i<m;i++)
{
scanf("%d%d%d",&s,&e,&t);
Map[s].push_back(edge(e,t));
Map[e].push_back(edge(s,t));
}
//输入虫洞
for(i=0;i<w;i++)
{
scanf("%d%d%d",&s,&e,&t);
Map[s].push_back(edge(e,-t));
}
// for(i=0;i<n;i++)
// {
// //for(j=0;j<n;j++)
// {
// printf("%d %d-----------",i,j);
// printf("%d %d\n",Map[1][0].e,Map[1][0].w);
// //printf("aaaaa");
// }
//
// }
if(spfa(1))
printf("YES\n");
else
printf("NO\n");
}
return 0;
}