POJ:3259 Wormholes(SPFA判断负环)

这个题最坑爹的地方在于有重边,因此有邻接矩阵比较方便。

所以无向图的时候要这样

if(w<gl[u][v])       gl[u][v]=gl[v][u]=w;

而无向图

  gl[u][v]=-w;

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<string>
#include<algorithm>
using namespace std;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int gl[505][505];
        memset(gl,0x7f,sizeof(gl));
        int INF=gl[0][0];
        int N,M,W;
        scanf("%d%d%d",&N,&M,&W);
        int u,v,w;
        for(int i=0; i<M; ++i)
        {
            scanf("%d%d%d",&u,&v,&w);
            if(w<gl[u][v])
                gl[u][v]=gl[v][u]=w;
        }
        for(int i=0; i<W; ++i)
        {
            scanf("%d%d%d",&u,&v,&w);
            gl[u][v]=-w;
        }
        int dist[505],cou[505]= {0};
        bool inq[505]= {0};
        memset(dist,0x7f,sizeof(dist));
        dist[1]=0;
        queue<int> q;
        q.push(1);
        cou[1]++;
        inq[1]=true;
        bool yes=false;
        while(!q.empty())
        {
            int tmp=q.front();
            q.pop();
            if(cou[tmp]>N)
            {
                yes=true;
                break;
            }
            for(int i=1; i<=N; ++i)
            {
                if(gl[tmp][i]!=INF&&gl[tmp][i]+dist[tmp]<dist[i])
                {
                    dist[i]=gl[tmp][i]+dist[tmp];
                    if(!inq[i])
                    {
                        q.push(i);
                        cou[i]++;
                        inq[i]=true;
                    }
                }
            }
            inq[tmp]=false;
        }
        if(yes) puts("YES");
        else puts("NO");
    }
    return 0;
}


 

下面这个是用邻接表实现的,处理重边的时候就比较麻烦了。。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<string>
#include<algorithm>
using namespace std;
struct Edge
{
    int from,to,cost;
    Edge(int a,int b,int c):from(a),to(b),cost(c) {}
};
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int N,M,W;
        scanf("%d%d%d",&N,&M,&W);
        int u,v,w;
        vector<Edge> adjlist[505];
        for(int i=0; i<M; ++i)
        {
            scanf("%d%d%d",&u,&v,&w);
            bool ok=false;
            for(int k=0; k<adjlist[u].size(); ++k)
            {
                int t=adjlist[u][k].to;
                if(t==v&&adjlist[u][k].cost>w)
                {
                    adjlist[u][k].cost=w;
                    for(int j=0; j<adjlist[v].size(); ++j)
                    {
                        int tt=adjlist[v][j].to;
                        if(tt==u&&adjlist[v][j].cost>w)
                        {
                            adjlist[v][j].cost=w;
                            break;
                        }
                    }
                    ok=true;
                    break;
                }
            }
            if(!ok)
            {
                adjlist[u].push_back(Edge(u,v,w));
                adjlist[v].push_back(Edge(v,u,w));
            }
        }
        for(int i=0; i<W; ++i)
        {
            scanf("%d%d%d",&u,&v,&w);
            bool ok=false;
            for(int i=0; i<adjlist[u].size(); ++i)
                if(adjlist[u][i].to==v)
                {
                    adjlist[u][i].cost=-w;
                    ok=true;
                    break;
                }
            if(!ok)
                adjlist[u].push_back(Edge(u,v,-w));
        }
        queue<int> q;
        int dist[505],cou[505]= {0};
        bool inq[505]= {0};
        memset(dist,0x7f,sizeof(dist));
        dist[1]=0;
        q.push(1);
        inq[1]=true;
        cou[1]++;
        bool yes=false;
        while(!q.empty())
        {
            int tmp=q.front();
            if(cou[tmp]>N)
            {
                yes=true;
                break;
            }

            for(int i=0; i<adjlist[tmp].size(); ++i)
            {
                int v=adjlist[tmp][i].to;
                if(dist[v]>dist[tmp]+adjlist[tmp][i].cost)
                {

                    dist[v]=dist[tmp]+adjlist[tmp][i].cost;
                    if(!inq[v])
                    {
                        q.push(v);
                        inq[v]=true;
                        cou[v]++;
                    }
                }
            }
            inq[tmp]=false;
            q.pop();
        }
        if(yes) puts("YES");
        else puts("NO");
    }
    return 0;
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值