poj 2983 spfa差分约束

题意:给出两种关于防御站位置的信息,一种是确切的信息,P A B X,表示A在B北面X距离的地方,另一种是V A B,表示只知道A在B的北面,且距离至少为1。问这些信息有没有矛盾。

思路:明显的差分约束。对于P A B X,列出X<=A-B<=X,然后转化为两个不等式即可。

注意队列的大小~~

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 1005
#define M 100005
#define INF 0x3fffffff
struct edge{
    int y,w,next;
}e[(M<<1)+N];
int first[N],dis[N],q[1000000],used[N],num[N];
int n,m,top;
void add(int x,int y,int w){
    e[top].y = y;
    e[top].w = w;
    e[top].next = first[x];
    first[x] = top++;
}
int relax(int x,int y,int w){
    if(dis[y] > dis[x]+w){
        dis[y] = dis[x]+w;
        return 1;
    }
    return 0;
}
int spfa(){
    int i,now,front,rear,y;
    front = rear = -1;
    for(i = 1;i<=n;i++)
        dis[i] = INF;
    q[++rear] = 0;
    memset(used, 0, sizeof(used));
    memset(num, 0, sizeof(num));
    used[0] = 1;
    while(front < rear){
        now = q[++front];
        used[now] = 0;
        for(i = first[now];i!=-1;i=e[i].next){
            y = e[i].y;
            if(relax(now,y,e[i].w) && !used[y]){
                used[y] = 1;
                q[++rear] = y;
                num[y]++;
                if(num[y] > n)
                    return 0;
            }
        }
    }
    return 1;
}
int main(){
    while(scanf("%d %d",&n,&m) !=EOF){
        int i,a,b,w;
        char op;
        top = 0;
        memset(first, -1, sizeof(first));
        getchar();
        for(i = 1;i<=m;i++){
            op = getchar();
            if(op == 'P'){
                scanf("%d %d %d\n",&a,&b,&w);
                add(a,b,-w);
                add(b,a,w);
            }else{
                scanf("%d %d\n",&a,&b);
                add(a,b,-1);
            }
        }
        for(i = 1;i<=n;i++)
            add(0,i,0);
        if(spfa())
            printf("Reliable\n");
        else
            printf("Unreliable\n");
    }
    return 0;
}


你可能感兴趣的:(poj 2983 spfa差分约束)