差分约束系统总结

来源:互联网 发布:android应用 性能优化 编辑:程序博客网 时间:2024/05/17 23:17

2011/10/08--2011/10/11四天的SPFA,Bellman_Ford,差分约束。

今天来个总结吧(虽说还有SPFA的优化算法没学,以后遇到题目再解决吧)

采用循序渐进的办法来阐述这几天的学习:

1.Bellman_Ford算法:

主要思想在于三角形不等式与“疏松”思想。当d[s,v]>d[s,u]+w[u,v]时,对边的权值进行疏松化。从写Bellman_Ford后我便学会了指针式的单链表的使用,话说还是自己重新看了一遍教材才会的。

//一下采用头插法,简单易懂Node *p=&Edge[edgeNum++];//声明指针p指向一块内存区域p->v=v;p->price=price;//对该内存进行初始化p->next=head[u];//将头指针指向的地址复制给p的next指针head[u]=p;//将头指针修改为p指向的内存区域,即Edge[edgeNum];
其实发现这种方法还是比数组的实现来得简单。
另外Bellman_Ford的实现:

//Bellman_Forddist[s]=0;for( int i=1;i<=vertNum;i++ )   for( int j=1;j<=edgeNum;j++ )      if( dist[Edge[j].v]>dist[Edge[j].u]+Edge[j].price )         dist[Edge[j].v]=dist[Edge[j].u]+Edge[j].pricefor( int j=1;j<=edgeNum;j++ )   if( dist[Edge[j].v]>dist[Edge[j].u]+Edge[j].price)         return false;return true;

时间复杂度大家都知道O(VE),从算法中可以出,每个点都进行了V次的疏松。在疏松完毕后若仍然存在疏松的条件,则可以判断有负环。这个算法只是用来求最短路径的。

2.SPFA

SPFA是对Bellman_Ford的一种优化;

bool spfa(){     bool used[MAXN];     int cnt[MAXN];     memset( used,0,sizeof(used) );     memset( cnt,0,sizeof(cnt) );     memset( dist,0xFF,sizeof(dist) );     queue<int>myQueue;     while( !myQueue.empty() ) myQueue.pop();          dist[s]=0;     myQueue.push(s);          while( !myQueue.empty() )     {            int u=myQueue.front();            myQueue.pop();            Node *p=ptr[u];            used[u]=false;            while( p )            {                   if( dist[p->v]<dist[u]+p->price )                   {                       dist[p->v]=dist[u]+p->price;                       if( !used[p->v] )                       {                           used[p->v]=true;                           myQueue.push(p->v);                           if( ++cnt[p->v]>N-1 )                               return false;                       }                   }                   p=p->next;            }     }     return true;}
数据结构为队列。首先将s源点入队。在队非空的时候进行循环。每次取队首的元素作为起点,当从起点出发对其他点进行了有效的疏松时,若该点不在队列中,则将其加入队列,并标记为在队列中。直到队列为空或者,某点入队次数>N-1时退出循环。

算法很容易理解,不加赘述。

SPFA主要用来判断问题是否有解(不形成负环)或者单源点的最短路径。

3.差分约束系统

差分约束系统其实就是Ax<=C,满足这个条件的三个矩阵。其中A每一行都由1,-1各一个组成。这样由m个约束条件对n个未知量构成的约束系统就称为差分约束系统了。系统存在无数组解或者无解两种情况。

由Xj-Xi<=C,等等的约束条件可以联想构图;

在这里,使用差分约束可以解决两类问题:

1.求最大值;

2.求最小值;

1>.求最大值问题。这类问题的约束图满足条件:

dist[v]<=dist[u]+w[u,v]

这个三角形不等式是不是很像SPFA的最短路径呢?其实用SPFA求最短路径。在求最短路径循环过程中符合dist[v]>dist[u]+w[u,v]时便进行疏松,最终会满足条件dist[v]<=dist[u]+w[u,v];这样通过SPFA求最短路径就是所求的最大值。另外还有一种理解就是dist[v]<=dist[u]+w[u,v],可以理解为对于所有的dist[u],dist[v]都满足该条件.那么显然就是dist[v]=min(dist[u]+w[u,v])都成立,也就是求最短路径了。可以这样理解的。

2>.求最小值问题。这类问题和求最大值问题类似。不过在求解的过程有稍有不同。

这样的约束图呢满足这条件dist[v]>=dist[u]+w[u,v];也就是对于所有的dist[u]都存在dist[v]>=dist[u]+w[u,v];也就是dist[v]=max(dist[u]+w[u,v]);这样就是求最长路径咯~

注意:dist[i]=-∞;否则最长路径求不出来.

以上就是求最小值用最长路径算法,最大值用最短路径求法。

另外构建差分约束的图,要善于捕捉题目中的隐含条件。另外差分约束系统只能解决>=或<=条件。连续的序列的差分约束可以使用前缀表达方法化为前几项的和。另外构建隐含的超级源点,将所有dist初始化,所有点入队,另外inq数组全部置为true;

基本上算是总结好了~收工~ 在遇到有难度的题再来添加完善~