关闭

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

标签: poj
200人阅读 评论(0) 收藏 举报
分类:


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;
}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:61021次
    • 积分:4045
    • 等级:
    • 排名:第7711名
    • 原创:356篇
    • 转载:4篇
    • 译文:0篇
    • 评论:11条
    最新评论