差分约束系统

//差分约束系统
//定理:给定一差分约束系统Ax≤b,设G=(V,E)为其相应的约束图。
//如果G不包含负权回路,即权值之和小于0 的环路。
//那么x=( d(v0,v1) , d(v0,v2) , … , d(v0,vn) )是此系统的一可行解,
//其中d(v0,vi)是约束图中v0到vi的最短路径(i=1,2,…,n)。
//如果G包含负权回路,那么此系统不存在可行解。
//所以可以用Bellman-Ford算法解决差分约束系统。



//求解差分约束系统,可以转化成图论的单源最短路径问题。
//观察xj-xi<=bk,会发现它类似最短路中的三角不等式d[v]<=d[u]+w[u,v]
//因此,以每个变量xi为结点,对于约束条件xj-xi<=bk,连接一条边(i,j),i到j,边权为bk。
//我们再增加一个源点s,s与所有定点相连,边权均为 0 。
//对这个图,以s为源点运行Bellman-ford算法(或SPFA算法),最终{dist[ i]}即为一组可行解。


#include
<iostream> //poj 2983 差分约束系统
using namespace std;


typedef
struct Edge{
int u, v; // 起点,重点
int weight; // 边的权值
}Edge;

Edge edge[
300000]; // 保存边的值
int dist[1010]; // 结点到源点最小距离

int nodenum, e,edgenum; // 结点数,边数,源点

// 初始化图
void init()
{
for(int i=0;i<=nodenum;++i)
dist[i]
=INT_MAX; //表示不可达
dist[0]=0;
char ch;
int a,b,x,i=0;
while(e--)
{
scanf(
" %c",&ch);
if(ch=='P') //P a,b,x a-b=x 可化为两个不等式:a-b>=x, a-b<=x
{
scanf(
"%d %d %d",&a,&b,&x); //cin会TLE
edge[++i].u=a;edge[i].v=b;edge[i].weight=-x;
edge[
++i].u=b;edge[i].v=a;edge[i].weight=x;
}
else
{
scanf(
"%d %d",&a,&b);
edge[
++i].u=a;edge[i].v=b;edge[i].weight=-1;
}
}
edgenum
=i;
}

// 松弛计算
void relax(int u, int v, int weight)
{
if(dist[v] > dist[u] + weight)
dist[v]
= dist[u] + weight;
}

bool Bellman_Ford()
{
for(int i=1; i<=nodenum-1; ++i)
for(int j=1; j<=edgenum; ++j)
relax(edge[j].u, edge[j].v, edge[j].weight);

// 判断是否有负环路
for(int i=1; i<=edgenum; ++i)
if(dist[edge[i].v] > dist[edge[i].u] + edge[i].weight)
return 0;
return 1;
}
int main()
{
while(cin >> nodenum >> e )
{
init();
if(Bellman_Ford())
printf(
"Reliable\n");
else
printf(
"Unreliable\n");
}
return 0;
}

  

posted on 2011-08-24 16:22  sysu_mjc  阅读(215)  评论(0编辑  收藏  举报

导航