这题用的是差分约束做的,要建立一个超级源点,P A B C 可以看做是 dist[A] - dist[B] >= c&&dist[A] - dist[B] <= c; V A B 可以看做是 dist[A] - dist[B] >= 1;
然后判断是否符合就用spfa的性质,如果一个点进出队列的次数大于点的个数,那么就存在负环,就可以判定不符合.
/*
time 454MS
mem 2552K
*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#define inf 100000005
#define maxn 1005
#define maxe 1000005
#define mem(a) memset(a, 0, sizeof(a))
using namespace std;
struct edge
{
int v, w;
int next;
}eg[maxe * 4];
int head[maxn], flag[maxn], flag2, egnum, num, dist[maxn], que[maxn * maxn];
bool vis[maxn];
void add(int u, int v, int w)
{
eg[egnum].v = v;
eg[egnum].w = w;
eg[egnum].next = head[u];
head[u] = egnum++;
}
void spfa()
{
long i, u, v, w, hd = 0, tail = 0;
mem(vis);
memset(dist, -inf, sizeof(dist));
que[hd++] = 0;
dist[0] = 0;
vis[0] = 1;
flag[0]++;
while (tail != hd)
{
u = que[tail++];
tail = tail % (maxn * maxn);
vis[u] = 0;
for (i = head[u];i != -1;i = eg[i].next)
{
v = eg[i].v;
w = eg[i].w;
if (dist[v] < dist[u] + w)
{
dist[v] = dist[u] + w;
if (!vis[v])
{
vis[v] = 1;
que[hd++] = v;
hd = hd % (maxn * maxn);
flag[v]++;
if(flag[v] > num)
{
flag2 = 1;
return;
}
}
}
}
}
return;
}
int main()
{
int i, a, b, c, n;
char ch;
while(scanf("%d%d%*c", &num, &n) != EOF)
{
mem(flag);
flag2 = 0;
egnum = 0;
memset(head, -1, sizeof(head));
for(i = 0;i < n;i++)
{
scanf("%c", &ch);
if(ch == 'P')
{
scanf("%d%d%d%*c", &a, &b, &c);
add(a, b, c);
add(b, a, -c);
}
else
{
scanf("%d%d%*c", &a, &b);
add(a, b, 1);
}
}
for(i = 1;i <= num;i++)
add(0, i, 0);
spfa();
if(flag2)
printf("Unreliable\n");
else
printf("Reliable\n");
}
return 0;
}