1. 程式人生 > >【POJ2983】Is the Information Reliable? ——差分約束

【POJ2983】Is the Information Reliable? ——差分約束

存在 tail src init lose ati family fin turn

題目大意:一天南北線上有n個防禦站,給出他們之間的位置關系,問有沒有可能存在這樣一種位置布置符合所給的位置關系。關系有兩種,一種是 P A B X,表示A在B北邊X光年的位置,V A B表示A在B北邊至少1光年位置。

分析:仍然考慮差分約束,容易想到,若關系為P,則

            s[a]-a[b]=c;

變換一下則變成:

            s[b]-s[a]<=-c;

            s[a]-a[b]<=c;

若關系為V,則

            s[b]-s[a]<=-1;

這樣轉換之後就變成了求最短路了,註意這道題可能無解,無解即表現為存在負環,判斷方法為:如果一個點入隊超過n次,則該圖存在負環,直接退出。

細節方面的話,註意讀入要使用字符串讀入,要使用超級源並且超級源到各點距離為0,多組數據的初始化以及存在負環的話需要在從隊首取出元素後立即將此元素標記為未入隊(因為有可能出現x->y權值為1,y->x權值為-2等情況)。

代碼:

技術分享
#include<cstdio>
#include<algorithm>
#include<cstring>
#define mem(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,127,sizeof(a))
const int maxn=1e5+5
; using namespace std; struct point{ int next,w,to; }e[maxn*3]; int tot,first[maxn],maxx=0,q[maxn]; int dis[maxn],sum[maxn]; bool vis[maxn]; int n,m,a,b,c; char ch[2]; int read() { int ans=0,f=1;char c=getchar(); while(c<0||c>9){if(c==-)f=-1;c=getchar();} while
(c>=0&&c<=9){ans=ans*10+c-48;c=getchar();} return ans*f; } void add(int u,int v,int wi) { tot++;e[tot].next=first[u];first[u]=tot;e[tot].to=v;e[tot].w=wi; } void init() { tot=0;mem(first);mem1(dis);mem(vis);mem(sum); for(int i=1;i<=n;i++)add(0,i,0); } bool spfa() { int head=0,tail=1; q[head]=0;vis[0]=1;dis[0]=0; while(head!=tail){ int x=q[head];head++;if(head>=100000)head=0; vis[x]=0; for(int i=first[x];i;i=e[i].next){ int to=e[i].to; if(dis[to]>dis[x]+e[i].w){ dis[to]=dis[x]+e[i].w; if(!vis[to]){ sum[to]++; vis[to]=1; q[tail]=to;tail++; if(tail>=100000)tail=0; if(sum[to]>n)return 0; } } } } return 1; } int main() { while(scanf("%d %d",&n,&m)==2){ init(); for(int i=1;i<=m;i++){ scanf("%s",ch);a=read();b=read(); if(ch[0]==P){ c=read(); add(a,b,-c);add(b,a,c); } else add(a,b,-1); } if(spfa())printf("Reliable\n"); else printf("Unreliable\n"); } return 0; }
POJ2983

【POJ2983】Is the Information Reliable? ——差分約束