poj3259 Wormholes(floyd||spfa判断负环)

原创 2016年05月31日 21:05:34


http://poj.org/problem?id=3259

题意:n个点,m个正权边,w个负权边,正权边为双向,负权边为单向,判断是否有负环。


思路:首先知道何为负环,例如有3个点编号1,2,3,任意两点之间都存在一条边,那么1,2,3存在一个环,其上权值和为负即为负环。floyd和spfa两种做法,floyd法卡的时间紧,不但要把min改成普通判断,输出也不能在函数内。整体来说floyd太容易超时了,判环条件就是判断对角线上的点,如果有负值,说明松弛过程中又回到了原来的点且更新比0小。spfa的判环条件就是某个点进入队列的次数超过n次,则存在负环(spfa无法处理带负环的图)。而dijkstra无法判断。


#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <queue>

using namespace std;

typedef long long LL;

const int N = 600;
const int INF = 0x3f3f3f3f;

int G[N][N], dis[N], num[N], n, s;
bool vis[N];

int floyd()
{
    for(int k = 1; k <= n; k++)
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= n; j++)
            {
        //        G[i][j] = min(G[i][j], G[i][k]+G[k][j]);
                if(G[i][k]+G[k][j] < G[i][j])
                    G[i][j] = G[i][k]+G[k][j];
            }
            if(G[i][i] < 0) return 1;
        }
    return 0;
}

int spfa()
{
    queue<int>que;
    for(int i = 1; i <= n; i++)
    {
        dis[i] = INF;
        num[i] = 0;
    }
    dis[1] = 0;
    vis[1] = true;
    que.push(1);
    while(!que.empty())
    {
        int now = que.front();
        que.pop();
        vis[now] = false;//记得还原!!
        for(int i = 1; i <= n; i++)
        {
            if(dis[now]+G[now][i]<dis[i])
            {
                dis[i] = dis[now]+G[now][i];
                if(!vis[i])
                {
                    vis[i] = true;
                    num[i]++;
                    if(num[i] > n) return 1;
                    que.push(i);
                }
            }
        }
    }
    return 0;
}

int main()
{
  //  freopen("in.txt", "r", stdin);
    int f, m, e, w, t;
    scanf("%d", &f);
    while(f--)
    {
        scanf("%d%d%d", &n, &m, &w);
        memset(vis, 0, sizeof(vis));
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
            {
                if(i == j) G[i][j] = 0;
                else G[i][j] = INF;
            }
        for(int i = 1; i <= m; i++)
        {
            scanf("%d%d%d", &s, &e, &t);
            if(t < G[s][e]) G[s][e] = G[e][s] = t;
        }
        for(int i = 1; i <= w; i++)
        {
            scanf("%d%d%d", &s, &e, &t);
            G[s][e] = -t;
        }
        int ans = floyd();
      //  int ans = spfa();
        if(ans) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

POJ 3259 Wormholes(判断负环&(Bellman-Ford|SPFA))

题目链接:kuangbin带你飞 专题四 最短路练习 F - Wormholes题意 农场主拥有很多农场,在这些农场之间有很多条路,以及单向的虫洞,每条路走完会花费一定的时间,而冲动可以回到之前的...

poj 3259 Wormholes(spfa判断负环)

Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 43863   Accepted: 16107...

POJ:3259 Wormholes(SPFA判断负环)

这个题最坑爹的地方在于有重边,因此有邻接矩阵比较方便。 所以无向图的时候要这样 if(w 而无向图   gl[u][v]=-w; #include #include #include #include...
  • kkkwjx
  • kkkwjx
  • 2013年10月21日 10:19
  • 479

POJ 3259 Wormholes (最短路 SPFA 判断负环)

POJ 3259 Wormholes (最短路 SPFA 判断负环) 题意: N个农场旅行 有M个路径 和 W个虫洞。 有M行 普通路径 S ,E, T。表示从地点S(E)到地点E...

POJ 3259 Wormholes SPFA 判断负环

题目链接: POJ—3259 Wormholes 题目大意: 给一个图,求有没有负环。 题目分析:第一次用SPFA(代码在后面) AC 代码(写的丑,勿喷)(bellmen-ford应该也可以...

POJ - 3259 Wormholes(判断负环, Bellman Ford,SPFA)

虫洞能够时光倒流,判断能否在回到出发的位置的时候在出发的时候之前。(判断是否存在负环) 初学最短路,尝试着用了三种方法判断: 1、Bellman Ford (令d全部为0,仅用来判断负环)    ...

POJ 3259 Wormholes(SPFA算法判断是否存在负环)

Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 36755   Accepted: 13457...

poj3259Wormholes【最短路SPFA判断负环】

Wormholes Time Limit : 4000/2000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other) Total...

POJ 3259 Wormholes 【SPFA 判断负环】

Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 36782   Accepted: 13467...
  • wyjwyl
  • wyjwyl
  • 2015年08月20日 10:14
  • 236

POJ3259 Wormholes 【SPFA判断负环】

Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 32111   Accepted: 11662...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:poj3259 Wormholes(floyd||spfa判断负环)
举报原因:
原因补充:

(最多只允许输入30个字)