模板_poj1201Intervals_差分约束系统解决(类区间问题)

来源:互联网 发布:数据波动率计算公式 编辑:程序博客网 时间:2024/05/21 10:42

poj1201题目链接

题意:

第一行输入n,下面输入n个限制条件,条件的格式为 ai bi ci,  0<=ai<=bi<=50000,1<=ci<=bi-ai+1.表示在区间[ai,bi]上至少选ci个点,使被选出的点的个数最少而且满足所有的限制条件,输出这个最小值。


差分约数系统的含义,其实就是如果有n个变量在m个形如aj-ai>=bk(类似于求最长路径)条件下,求解的此不等式的方法。
 而这种不等式的解法其实就是转化为图论的最小路的算法求解的。我们将上面的不等式边形后得到aj>=ai+bk正好就可以看做是从ai到aj权值是bk的一条路径最短的边。这样一来,只要依照题目的条件写出一系列这样的不等式,也就是相当于按照题意增加了一些合法的边,也就完全转化为了最短路的算法。转化详解
但要注意的是,由于查分约束系统里常常会有负权边,所以为了避免负权回路,往往用Bellman-Ford或是SPFA求解(存在负权回路则最短路不存在)。

差分约束系统讲解



看时间:第一次我用的是数组实现邻接表,第二个我我用的是vector动态数组。在做poj3159题的时候用vector就直接超时了。。找了半天错也没找出来,更好笑的事那个用的还是栈,这个用栈直接就超时了。。。我到现在还是不解为甚用vector会超时!觉得没差啊~~~想了下这两道题的共同点就是数据量大。边多点多。就是想不通为什么在时间上的差异这么大,让我研究一下吧(知道的可以给我留下言啊,一起讨论下)。。

Sample Input

53 7 38 10 36 8 11 3 110 11 1

Sample Output

6

#include<stdio.h>#include<string.h> #include<vector>#include<queue>#define inf 1<<28using namespace std;#define MIN(a,b) a<b?a:b#define MAX(a,b) a>b?a:bstruct node{int u,v,w,next;}e[50005*3];int vis[50005];int dis[50005];int head[50005];int num,maxi,mini;void add_edge(int u,int v,int w){e[num].v=v;e[num].w=w;    e[num].next=head[u];head[u]=num++;}void SPFA(){memset(vis,0,sizeof(vis));int v,i,w,u;queue<int>Q;Q.push(mini);vis[mini]=1;dis[mini]=0;while(!Q.empty()){u=Q.front();Q.pop();vis[u]=0;for(i=head[u];i!=-1;i=e[i].next){v=e[i].v;w=e[i].w;if(dis[v]<dis[u]+w){dis[v]=dis[u]+w;if(!vis[v]){vis[v]=1;Q.push(v);}}  }}}int main(){int i,a,b,c,n;while(~scanf("%d",&n)){memset(dis,-1,sizeof(dis));    memset(head,-1,sizeof(head));num=0;mini=inf;maxi=-inf;for(i=0;i<n;i++){scanf("%d%d%d",&a,&b,&c);add_edge(a,b+1,c);mini=MIN(mini,a);maxi=MAX(maxi,b+1);}for(i=mini;i<maxi;i++){add_edge(i,i+1,0);add_edge(i+1,i,-1);}SPFA();printf("%d\n",dis[maxi]);}return 0;}


0 0
原创粉丝点击