poj 2983--Is the Information Reliable?

本文介绍了一种使用并查集结合Bellman-Ford算法来检测图中是否存在负环的方法。通过处理输入信息转化为边集合,并利用Bellman-Ford算法进行松弛操作判断负环的存在性。

同POJ 1021,建立差分约束系统,只不过此题要求检查负环。

  1. 建图时精确信息的等号可以化为两个不等式。
  2. 利用并查集检查负环。

#include<cstdio>
#include<cstring>
using namespace std;
#define maxN 1005
#define INF 0x7F7F7F7F
#define maxE 200005

int nodeNum,edgeNum;

struct edge
{
    short px,py;
    int w;
}edges[maxE];

int str2num()
{
    int num = 0;
    char c;
    while((c = getchar())&&(c != ' ')&&(c != '\n')&&(c >= 0))
    {
        num *= 10;
        num += c-'0';
    }
    return num;
}

bool bellman_ford()
{
    int i,j,w;
    int dis[maxN];
    int fa[maxN];
    char IsRelax;
    int y,x;
    memset(dis,0,sizeof(dis));
    for(i = 1;i <= nodeNum;i++)
        fa[i] = i;
    for(i = 0;i < nodeNum-1;i++)
    {
        IsRelax = false;
        for(j = 0;j < edgeNum;j++)
        {
            x = edges[j].px;
            y = edges[j].py;
            w = edges[j].w;
            if(dis[y] > dis[x]+w)
            {
                if(fa[x] == y) return true;<span style="white-space:pre">	</span>//并查集检查负环
                fa[y] = fa[x];
                dis[y] = dis[x]+w;
                IsRelax = true;
            }
        }
        if(!IsRelax) return false;
    }
    for(j = 0;j < edgeNum;j++)
    {
        x = edges[j].px;
        y = edges[j].py;
        w = edges[j].w;
        if(dis[y] > dis[x]+w)
        {
            return true;
        }
    }
    return false;
}

int main()
{
    int i;
    int messageNum;
    int a,b,dis;
    char c;
    while(~scanf("%d%d",&nodeNum,&messageNum))
    {
        getchar();
        edgeNum = 0;
        for(i = 0;i < messageNum;i++)
        {
            c = getchar();
            getchar();
            a = str2num();
            b = str2num();
            if(c == 'P')
            {
                dis = str2num();
                edges[edgeNum].px = a;
                edges[edgeNum].py = b;
                edges[edgeNum++].w = -1*dis;
                edges[edgeNum].px = b;
                edges[edgeNum].py = a;
                edges[edgeNum++].w = dis;
            }
            else
            {
                edges[edgeNum].px = a;
                edges[edgeNum].py = b;
                edges[edgeNum++].w = -1;
            }
        }
        if(bellman_ford()) printf("Unreliable\n");
        else printf("Reliable\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值