poj2983(差分约束系统)Is the Information Reliable?

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

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
(主要是自己想出了整个过程,太棒了!)
题目大意:有两个敌对势力,a方想弄清楚b方的n个防御站的位置,通过一些地下组织。 地下组织提供多条情报,你要判断这些情报是否可靠。 情报分为两种:P A B X:A站在B站北边X公里; V A B:A站在B站北边至少1公里,但具体多远不清楚。现在给出n个站和m条情报,判断这m条情报是否可靠。

思路:换一条数轴,规定南方的起始点(有点抽象,我也不知道怎么描述,反正就是规定一个起始点)为数轴的原点,X[i]为距离南方(原点)的长度。
那么对于P情报:X[i]在X[j]北方X距离,则表示为X[i]-X[j]=X;
同理V情报就是:X[i]-X[j]>=1;


将所有P情报中的等式转化成不等式
X[i]-X[j]=W--->X[i]-X[j]>=W   X[i]-X[j]<=W;
有三种不等  -------------〉(到此,应该想到图的转化了,统一不等式符号)
X[i]-X[j]>=W              X[j]-X[i]<=-W;
X[i]-X[j]<=W;              X[i]-X[j]<=W;
X[i]-X[j]>=1;             X[j]-X[i]<=-1;

就构成了差分约束系统
由于本题判断情报是否可信,等价于是否存在一组解X[],等价于转化图是否存在最短路,
既判断图中是否存在  负环  。

分析至此,后面的就是建图了,用SPFA或者BELLMAN-FORD判断是否存在负环。
用SPFA需要添加一个虚拟源点(0),使得虚拟源点(0)到其他所有节点的边权值为0,保证图的连通性.

代码如下:
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <queue>
using namespace std;
const int inf=100000000;
const int maxn=2000;
const int maxe=2000000;
struct NodeEdges
{
    int to;
    int next;
    int w;
};
NodeEdges edges[maxe];
int head[maxn],dist[maxn],outque[maxn];
bool inque[maxn];
int NumEdges,n,m;
void AddEdges(int u,int v,int w)
{
    NumEdges++;
    edges[NumEdges].to=v;
    edges[NumEdges].w=w;
    edges[NumEdges].next=head[u];
    head[u]=NumEdges;
}
bool Spfa(int s,int n)
{
    memset(outque,0,sizeof(outque));
    memset(inque,0,sizeof(inque));
    for(int i=0;i<=n;i++)   dist[i]=inf;
    dist[s]=0;
    queue<int>q;
    q.push(s);
    inque[s]=true;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        inque[u]=false;
        outque[u]++;
        if(outque[u]>n) return false;
        for(int k=head[u];k!=-1;k=edges[k].next)
        {
            if(dist[edges[k].to]>dist[u]+edges[k].w)
            {
                dist[edges[k].to]=dist[u]+edges[k].w;
                if(!inque[edges[k].to])
                {
                    inque[edges[k].to]=true;
                    q.push(edges[k].to);
                }
            }
        }
    }
    return true;
}
int main()
{
	//freopen("in.txt","r",stdin);
    while(scanf("%d%d",&n,&m)==2)
    {
        memset(dist,0,sizeof(dist));
        memset(head,-1,sizeof(head));
        memset(edges,0,sizeof(edges));
        NumEdges=0;
        while(m--)
        {
            int u,v,w;
            char str[30];
            scanf("%s",str);
            if(str[0]=='P')
            {
                scanf("%d%d%d",&u,&v,&w);
                AddEdges(u,v,-w);
                AddEdges(v,u,w);
            }
            else
            {
                scanf("%d%d",&u,&v);
                AddEdges(u,v,-1);
            }
        }
        for(int i=0;i<=n;i++)   AddEdges(0,i,0);
        if(Spfa(0,n+1))
            printf("Reliable\n");
        else
            printf("Unreliable\n");
    }
	return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值