【spfa求负权回路】poj 3259 Wormholes

版权声明:转载标注来源喔~ https://blog.csdn.net/iroy33/article/details/89404138

题意:field块地,path条路,hole个虫洞,虫洞是一条单向路,不但会把你传送到目的地,而且时间会倒退Ts。每条路给出起点、终点和经过时间,我们的任务是判断能否从某地出发,在过去的某个时间回到该地。

思路:即判断是否有负权回路,有的话就能回到原地。

关于SPFA:SPFA 在形式上和广度(宽度)优先搜索非常类似,不同的是bfs中一个点出了队列就不可能重新进入队列,
  但是SPFA中一个点可能在出队列之后再次被放入队列,也就是一个点改进过其它的点之后,过了一段时间可能本身被改进(重新入队),于是再次用来改进其它的点,这样反复迭代下去。  由dijkstra可知,源点先入队,之后n-1个点逐次入队
  如果一个点被改进的次数大于n-1,说明存在负环。(参考LRJ紫书)
 

//cnt忘记初始化导致Runtime error
/*
  SPFA 在形式上和广度(宽度)优先搜索非常类似,不同的是bfs中一个点出了队列就不可能重新进入队列,
  但是SPFA中一个点可能在出队列之后再次被放入队列,也就是一个点改进过其它的点之后,过了一段时间可能本身被改进(重新入队),
  于是再次用来改进其它的点,这样反复迭代下去。
  由dijkstra可知,源点先入队,之后n-1个点逐次入队
  如果一个点被改进的次数大于n-1,说明存在负环
  参考LRJ紫书

*/
#include<stdio.h>
#include<queue>
#include<cstring>
using namespace std;
const int inf=0x3f3f3f3f;
const int MAXE = 5500;
const int MAXN = 550;
int vis[MAXN],num[MAXN],dist[MAXN],head[MAXN];
int cnt;//记录边数
int n,m,w;
struct Edge
{
    int v,w,next;
}edge[MAXE];
void AddEdge(int u, int v, int w)
{
    edge[cnt].v = v;
    edge[cnt].w = w;
    edge[cnt].next = head[u];
    head[u] = cnt++;
}
bool spfa()
{
    memset(vis, 0, sizeof(vis));
    memset(num, 0, sizeof(num));
    for(int i = 1; i <= n; ++i)
        dist[i] = inf;
    queue<int>q;
    q.push(1);
    dist[1] = 0;
    vis[1] = 1;
    num[1]++;
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        vis[u] = 0;
        for(int i = head[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].v;
            if(dist[v] > dist[u] + edge[i].w)
            {
                dist[v] = dist[u] + edge[i].w;
                if(!vis[v])
                {
                    q.push(v);
                    vis[v] = 1;
                    num[v]++;
                    if(num[v] > n-1)   //结点v被松弛的次数超过n-1次
                        return true;

                }
            }

        }

    }
    return false;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        memset(head,-1,sizeof(head));
        cnt=0;
        scanf("%d%d%d",&n,&m,&w);
        for(int i = 1; i <= m; ++i)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            AddEdge(a, b, c);
            AddEdge(b, a, c);
        }
        for(int i = 1; i <= w; ++i)
        {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            AddEdge(a, b, -c);
        }
        if(spfa()) printf("YES\n");
        else printf("NO\n");
    }
    return 0;

}

猜你喜欢

转载自blog.csdn.net/iroy33/article/details/89404138