差分约束就是一推
a1-a2<=k1
a2-a3<=k2
a3-a1<=k3
.....
之类的不等式组...求解差分约束也就是求解其中的一个解...如果能得到一组解..那么所有的数加同一个数那么不等式显然是成立的...也就是每个数可以取到任意值..那就确定一个数,来求出一组解..假设先给 a[ s] 一个初值...d [ s ] [ v ] 代表当 a [ s ] 为这个确定值时 a [ v ] 可以为的数...w [ u ] [ v ] 是值 u 与 v 之间的关系...如 av-au=k 则 w [ u ] [ v ] = k...可以通过反证法推倒出:
d [ s ] [ v ] <= d [ s ] [ u ] + w [ u ] [ v ]
小于等于关系...可能有大于等于..等于...>=很好处理..两边同时乘以-1就可以了...等于的情况..就把等于拆成两个不等式...例如ai-aj=k..则拆成 ai-aj<=k , aj-ai<=-k .. 显然这两个不等式的唯一解就是 ai-aj..但把其拆成了小于等于关系...符合差分约束的条件...
定任意一个点为原点...值也可以是任意值...然后做一次Bellman-Ford..得出的 d [ i ] 就是在这组解中ai的值...
负环...那么只要在做完Bellman-Ford再判断一下有没有负环就可以了...
具体的一道题POJ-2983,是给出一些点的位置关系...有确定的也有模糊的...问这些信息是不是没有矛盾是正确的..
负环..有负环就代表该不等式组无解..输出Unreliable..无负环代表有解~~这组信息可以推断出一组位置关系..则输出Reliable...
这道题要注意的就是...模糊关系时给的>=1..所以要记得转化成小于等于...这里没注意WA了好久...囧
Ps: 是<=..不是<..<的话要化成 <=k-1 !!!
Program:
#include<iostream>
using namespace std;
struct pp
{
int x,y,k;
}line[300001];
int n,m,i,x,y,k;
char c;
bool Bellman_Ford()
{
int i,times,d[1001];
memset(d,0x7F,sizeof(d));
d[1]=0;
for (times=1;times<=n;times++)
for (i=1;i<=m;i++)
if (d[line[i].y]>d[line[i].x]+line[i].k)
d[line[i].y]=d[line[i].x]+line[i].k;
for (i=1;i<=m;i++)
if (d[line[i].y]>d[line[i].x]+line[i].k) return false;
return true;
}
int main()
{
while (~scanf("%d%d",&n,&m))
{
i=m;
m=0;
while (i--)
{
c=getchar();
while (c!='V' && c!='P' ) c=getchar(); ;
if (c=='P')
{
scanf("%d%d%d",&y,&x,&k);
m++;
line[m].x=x; line[m].y=y; line[m].k=k;
m++;
line[m].x=y; line[m].y=x; line[m].k=-k;
}else
{
scanf("%d%d",&x,&y);
m++;
line[m].x=x; line[m].y=y; line[m].k=-1;
}
}
if (Bellman_Ford()) printf("Reliable\n");
else printf("Unreliable\n");
}
return 0;
}