POJ 2983 Is the Information Reliable (差分约束 bell/spfa判断负环)

16 篇文章 1 订阅
11 篇文章 0 订阅


Is the Information Reliable?
Time Limit: 3000MS Memory Limit: 131072K
Total Submissions: 13804 Accepted: 4334

Description

The galaxy war between the Empire Draco and the Commonwealth of Zibu broke out 3 years ago. Draco established a line of defense called Grot. Grot is a straight line with N defense stations. Because of the cooperation of the stations, Zibu’s Marine Glory cannot march any further but stay outside the line.

A mystery Information Group X benefits form selling information to both sides of the war. Today you the administrator of Zibu’s Intelligence Department got a piece of information about Grot’s defense stations’ arrangement from Information Group X. Your task is to determine whether the information is reliable.

The information consists of M tips. Each tip is either precise or vague.

Precise tip is in the form of P A B X, means defense station A is X light-years north of defense station B.

Vague tip is in the form of V A B, means defense station A is in the north of defense station B, at least 1 light-year, but the precise distance is unknown.

Input

There are several test cases in the input. Each test case starts with two integers N (0 < N ≤ 1000) and M (1 ≤ M ≤ 100000).The next M line each describe a tip, either in precise form or vague form.

Output

Output one line for each test case in the input. Output “Reliable” if It is possible to arrange N defense stations satisfying all the M tips, otherwise output “Unreliable”.

Sample Input

3 4
P 1 2 1
P 2 3 1
V 1 3
P 1 3 1
5 5
V 1 2
V 2 3
V 3 4
V 4 5
V 3 5

Sample Output

Unreliable
Reliable


给一段信息,有关于N个点,M条信息。其中每一条信息:

1、P A B X,意思是A站点在B站点北X光年

2、V A B,意思是A站点在B站点北,但不知道确切距离,最少一光年。

对于给出的这段信息,求是否是真是的消息,因为错误的消息有矛盾的信息。


思路:将具体的x,转化成 >= <=,然后直接spfa就好了

spfa代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <queue>
using namespace std;
const int maxn = 1005;
const int maxe = 100005;
const int INF = 1e9;
int k, head[maxn], book[maxn], n, m, cnt[maxn], dis[maxn];
char cmd;
struct node
{
    int v, w, next;
}edge[maxe*2];
void addEdge(int u, int v, int w)
{
    edge[k].v = v;
    edge[k].w = w;
    edge[k].next = head[u];
    head[u] = k++;
}
void spfa()
{
    memset(book, 0, sizeof(book));
    memset(cnt, 0, sizeof(cnt));
    for(int i = 0; i < maxn; i++) dis[i] = INF;
    queue<int> q;
    q.push(0);
    book[0] = 1;
    cnt[0] = 1;
    dis[0] = 0;
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        book[u] = 0;
        for(int i = head[u]; i != -1; i = edge[i].next)
        {
            int to = edge[i].v, w = edge[i].w;
//            cout << to << ' ' << dis[to] << endl;
//                cout << dis[to] << ' ' << dis[u]+w <<endl;
            if(dis[to] > dis[u] + w)
            {
                dis[to] = dis[u] + w;
                if(!book[to])
                {
                    q.push(to);
                    if(++cnt[to] > n+1)
                    {
                        printf("Unreliable\n");
                        return ;
                    }
//                    cout << cnt[to] << endl;
                    book[to] = 1;
                }
            }
        }
    }
    printf("Reliable\n");
    return;
}
int main()
{
    while(~scanf("%d%d", &n, &m))
    {
        memset(head, -1, sizeof(head));
        k = 1;
        int x, y, z;
        for(int i = 1; i <= m; i++)
        {
            scanf(" %c", &cmd);
            if(cmd == 'P')
            {
                scanf("%d%d%d", &y, &x, &z);
                addEdge(x, y, z);
                addEdge(y, x, -z);
            }
            if(cmd == 'V')
            {
                scanf("%d%d", &y, &x);
                addEdge(y, x, -1);
            }
        }
        for(int i = 1; i <= n; i++)
            addEdge(0, i, 0);
        spfa();
    }
    return 0;
}


Bellman-Ford

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>

#define Infp 0x7fffffff
#define Infn 0x80000000
#define DisCon 1000000000
#define MAX  999999999
#define MIN -999999999

#define Z(a) memset(a, 0, sizeof(a))
#define C(a, b) memcpy(a, b, sizeof(b))
#define Pi acos(-1)
#define FMAX (1E300)
#define FMIN (-1E300)
#define feq(a, b) (fabs((a)-(b))<1E-6)
#define flq(a, b) ((a)<(b)||feq(a, b))
#define RG 1005

struct Edge
{
    int b;
    int e;
    int dis;
}e[200010];//简单的记录边的信息

int bell(int en, int pn)
{
    int dis[pn+1];
    int chg;

    dis[0]=0;
    for(int i=1; i<=pn; i++)
        dis[i]=DisCon;//这是为了防止溢出才不用最大值
    for(int i=0; i<pn; i++)
    {
        chg=0;
        for(int j=0; j<en; j++)
            if(dis[e[j].e]>dis[e[j].b]+e[j].dis)//松弛操作
            {
                dis[e[j].e]=dis[e[j].b]+e[j].dis;
                chg=1;//如果最终趋于稳定,就是说肯定没有负权回路了
            }
        if(!chg)return 1;
/*************解释*****************************
结合《算法导论》的解释,如果从单源出发,而且图是无负权回路的,
那么到任何一个短点的最短路径最多只包含|V|-1条边,而上述代码最
外层的循环次数是|V|次,就是最多将构造含有|V|条边的最短路集合。
假设循环不断进行,一直有最短路被发现(也即一直有松弛的路径更新
),直到i>|V|而退出,这说明这时构造出了一条最短路是有多于|V|条
边的,与初衷矛盾,所以这时说明了图是有负权回路的!
*********************************************/
    }
    return 0;
}

int main()
{
    int N, M;

    while(scanf("%d%d", &N, &M)!=EOF)
    {
        int en=0;
        while(M--)
        {
            getchar();

            char c;
            scanf("%c", &c);
            if(c=='P')//具体的信息,双向的边都要构造
            {
                int a, b, dis;

                scanf("%d%d%d", &a, &b, &dis);
                e[en].b=a;
                e[en].e=b;
                e[en++].dis=dis;
                e[en].b=b;
                e[en].e=a;
                e[en++].dis=-dis;
            }
            else//模糊的信息,据说边长一定大于1,只构造单向的边
            {
                int a, b;
                scanf("%d%d", &a, &b);
                e[en].b=b;
                e[en].e=a;
                e[en++].dis=-1;
            }
        }

        if(bell(en, N))printf("Reliable\n");
        else printf("Unreliable\n");
    }

    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值