POJ 3259 Wormholes 判断负环(spfa)

大概题意:农场里面有n个点m条边w个虫洞,m条边是双向边...a->b,b->a都是花费c分钟,虫洞的话是单向的,a点到b点时间会倒流c分钟就是-c分钟,然后问农场主是否能看到之前的自己...

大概也是个环?就是从起点出发在回到起点之后最短路更新最后从0能否变为负数...能负数就是能看到之前自己...大概是个负环吧...老老实实的去看spfa判断负环去了....

套了个模板...

发现了一个优化,因为这个题并不是一定要判断存在负环..所以可以再每次从队列中取出一个x进行松弛操作后判断一下dis[1]是否小于0,小于0就符合要求就是yes了...按照一个正常判断负环是906MS...判断小于0是235MS...差别还是蛮大的...

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
#define inf 200000000
int map[555][555],used[555];
int dis[555],n,num[555];
int spfa()
{
    queue<int> q;
    memset(used,0,sizeof(used));
    memset(num,0,sizeof(num));
    for(int i=1; i<=n; i++)
        dis[i]=inf;
    dis[1]=0;
    q.push(1);
    num[1]=1,used[1]=1;
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        used[x]=0;
        for(int i=1; i<=n; i++)
        {
            if(dis[i]>dis[x]+map[x][i])
            {
                dis[i]=dis[x]+map[x][i];
                if(!used[i])
                {
                    q.push(i);
                    used[i]=1;
                    num[i]++;
                    if(num[i]==n)
                        return 1;
                }
            }
        }
        if(dis[1]<0)//此处可以加一个优化...来判断是否提前符合了题意
            return 1;
    }
    return 0;
}
int main()
{
    int T,m,w;
    cin>>T;
    while(T--)
    {
        cin>>n>>m>>w;
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
                map[i][j]=inf;
        }
        for(int i=0; i<m; i++)
        {
            int u,v,s;
            cin>>u>>v>>s;
            map[u][v]=map[v][u]=min(s,map[u][v]);
        }
        for(int i=0; i<w; i++)
        {
            int u,v,s;
            cin>>u>>v>>s;
            map[u][v]=min(map[u][v],-s);
        }
        if(spfa())
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值