POJ3259,spfa算法求负环

首先需要明确的是,如果一个图里面有负环,那么用spfa算法时,存在一个点放进队列的次数超过n。可以这样想,既然为负,那么每放进一次,结果就变小,再放进去,再小,所以一直这样下去,有点高中生物中的正反馈的意味…
其他的就是spfa算法了。
详见代码:

/*************************************************************************
    > File Name: main.cpp
    > Author:Eagles 
    > Mail:None 
    > Created Time: 2018年09月09日 星期日 18时08分28秒
    > Description:POJ3259,spfa算法 
 ************************************************************************/

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
using namespace std;
#define N 1000
struct node
{
    int to;
    int val;
    int nex;
}E[50000];//边
int head[N];
bool vis[N];//该点是否被放进队列中
int dis[N];
int used[N];//被放进队列的次数,大于n,则存在负环
int t,n,m1,m2;
int cnt;
void addEdge(int a, int b, int val)
{
    E[cnt].val=val;
    E[cnt].to=b;
    E[cnt].nex=head[a];
    head[a]=cnt++;
}

void init()
{
    memset(head,-1,sizeof(head));

    for (int i=0; i<n; i++)
        dis[i]=111111;

    scanf("%d%d%d",&n,&m1,&m2);

    for (int i=0; i<m1; i++)
    {
        int a,b,val;
        scanf("%d%d%d",&a,&b,&val);

        addEdge(a-1,b-1,val);
        addEdge(b-1,a-1,val);
    }

    for (int i=0; i<m2; i++)
    {
        int a,b,val;
        scanf("%d%d%d",&a,&b,&val);
        addEdge(a-1,b-1,-val);
    }
}

bool spfa(int s)
{
    dis[s]=0;
    memset(vis,false,sizeof(vis));
    memset(used,0,sizeof(used));
    queue<int>q;
    q.push(s);


    while (!q.empty())
    {
        int cur=q.front();
        q.pop();

        if (used[cur]>n)
            return true;

        int k=head[cur];
        vis[cur]=false;

        while (k != -1)
        {
            if (dis[E[k].to]>dis[cur]+E[k].val)
            {
                dis[E[k].to]=dis[cur]+E[k].val;
                if (!vis[E[k].to])
                {
                    q.push(E[k].to);
                    used[E[k].to]++;
                    vis[E[k].to]=true;
                }
            }
            k=E[k].nex;
        }

    }
    return false;
}

int main()
{
    while (~scanf("%d",&t))
    {
        while (t--)
        {
            init();

            int i;

            for ( i=0; i<n; i++)
            {
                if (spfa(i))
                {
                    printf("YES\n");
                    break;
                }
            }

            if (i>=n)
                printf("NO\n");
        }
    }
    return 0;
}
发布了45 篇原创文章 · 获赞 2 · 访问量 3091

猜你喜欢

转载自blog.csdn.net/wysiwygo/article/details/82561041