UVA 558 判断负环

        边上带有负值的单源最短路径。

Bellman-Ford算法:


#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 2000+5
#define INF 1000000
using namespace std;
int u[MAXN],v[MAXN],w[MAXN],n,m,d[1005];
int main()
{
//    freopen("in.txt","r",stdin);
    int cas;
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d%d",&n,&m);
        for(int i=0;i<m;i++)
            scanf("%d%d%d",&u[i],&v[i],&w[i]);
        for(int i=0;i<n;i++)
            d[i]=INF;
        d[0]=0;
        for(int k=0;k<n-1;k++)
        {
            for(int i=0;i<m;i++)
            {
                int x=u[i],y=v[i];
                if(d[x]<INF)  d[y]=min(d[y],d[x]+w[i]);
            }
        }
        bool ok=false;
        for(int i=0;i<m;i++)
        {
            int x=u[i],y=v[i];
            if(d[x]<INF&&d[y]>d[x]+w[i])
                {
                    ok=true;
                    puts("possible");
                    break;
                }
        }
        if(!ok)
            puts("not possible");
    }
    return 0;
}

SPFA算法(邻接表):

#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
#define MAXN 2000+5
#define INF 1000000
using namespace std;
int u[MAXN],v[MAXN],w[MAXN],n,m,d[1005],first[1005],next[MAXN];
void read_graph()
{
    scanf("%d%d",&n,&m);
    for(int i=0; i<n; i++)
        first[i]=-1;
    for(int e=0; e<m; e++)
    {
        scanf("%d%d%d",&u[e],&v[e],&w[e]);
        next[e]=first[u[e]];
        first[u[e]]=e;
    }
}
bool ok;
void spfa()
{
    queue<int>q;
    ok=false;
    int vis[1005];
    memset(vis,0,sizeof(vis));
    bool inq[1005];
    d[0]=0;
    for(int i=1;i<n;i++)
        d[i]=INF;
    memset(inq,0,sizeof(inq));
    q.push(0);
    while(!q.empty())
    {
        int x=q.front();q.pop();
        inq[x]=false;
        for(int e=first[x];e!=-1;e=next[e])
        {
            if(d[v[e]]>d[x]+w[e])
            {
                d[v[e]]=d[x]+w[e];
                if(!inq[v[e]])
                {
                    inq[v[e]]=true;
                    vis[v[e]]++;
                    if(vis[v[e]]>n)
                    {
                        ok=true;
                        return ;
                    }
                    q.push(v[e]);
                }
            }
        }
    }
}
int main()
{
   // freopen("in.txt","r",stdin);
    int cas;
    scanf("%d",&cas);
    while(cas--)
    {
        read_graph();
        spfa();
        if(ok)
            puts("possible");
        else puts("not possible");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值