【poj2983】 Is the Information Reliable?
http://poj.org/problem?id=2983 (题目链接)
一个SB错误TLE了半个小时。。。
题意
一条直线上有n个点,给出m条信息,若为P则表示点A在点B的北方X米,若为V则表示A在B的北方。判断给出的信息是否合法。
Solution
对于P,A-B=X等价于是A-B>=X && A-B<=X(B-A>=-X)。
对于V,A-B>=1。
所以我们就可以利用差分约束去求解这个问题,在图上跑SPFA最长路判断是否存在正环。
注意设置一个超级源点使得图联通。
代码
// poj2983 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #define LL long long #define inf 2147483640 #define Pi acos(-1.0) #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); using namespace std; inline LL getint() { int f,x=0;char ch=getchar(); while (ch<='0' || ch>'9') {if (ch=='-') f=-1;else f=1;ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();} return x*f; } const int maxn=1010,maxm=100010; struct edge {int to,next,w;}e[maxm<<2]; int head[maxn],dis[maxn],vis[maxn],cnts[maxn],n,cnt,m; void link(int u,int v,int w) { e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].w=w; } bool SPFA() { deque<int> q; for (int i=1;i<=n;i++) dis[i]=-inf,cnts[i]=0,vis[i]=0; q.push_back(n+1); dis[n+1]=0; vis[n+1]=1; cnts[n+1]=1; while (!q.empty()) { int x=q.front(); q.pop_front(); vis[x]=0; for (int i=head[x];i;i=e[i].next) if (dis[e[i].to]<dis[x]+e[i].w) { dis[e[i].to]=dis[x]+e[i].w; if (!vis[e[i].to]) { if (++cnts[e[i].to]>n) return 1; vis[e[i].to]=1; if (!q.empty() && dis[e[i].to]<dis[q.front()]) q.push_back(e[i].to); else q.push_front(e[i].to); } } } return 0; } int main() { while (scanf("%d%d",&n,&m)!=EOF) { for (int i=1;i<=n+1;i++) head[i]=0; cnt=0; while (m--) { int u,v,w; char ch[5]; scanf("%s ",ch); if (ch[0]=='P') { scanf("%d%d%d",&u,&v,&w); link(v,u,w); link(u,v,-w); } else { scanf("%d%d",&u,&v); link(v,u,1); } } for (int i=1;i<=n;i++) link(n+1,i,0); if (SPFA()) puts("Unreliable"); else puts("Reliable"); } return 0; }
This passage is made by MashiroSky.