现在的位置: 首页 > 综合 > 正文

【图论01】最短路 1004 Intervals

2014年03月22日 ⁄ 综合 ⁄ 共 1456字 ⁄ 字号 评论关闭

算法思路:用最短路解决差分约束,Bellman-Ford算法。

题目大意:有n个区间,每个区间有3个值,ai,bi,ci代表,在区间[ai,bi]上至少要选择ci个整数点,ci可以在区间内任意取不重复的点
现在要满足所有区间的自身条件,问最少选多少个点

解题思路:
差分约束的思想:定义s[i]为[X, i]区间上“可能”(因为采取贪心的策略,一开始并不是最优)取的最少的点的个数,可以肯定的是s[bi]-s[ai-1]>=ci; 为什么要ai-1,是因为ai也要选进来
在一个是s[i]-s[i-1]<=1;
s[i]-s[i-1]>=0
所以整理上面三个式子可以得到约束条件:
①s[ai-1]-s[bi] <= -ci
②s[i]-s[i-1] <= 1
③s[i-1]-s[i] <= 0

而我们要所求的是从区间的最小点到区间最大点的所取的点的总个数最小。所以从源点(所有区间的最小点)到终点(所有区间的最大点)求最短路
这里要注意边界问题,就是最小点也要取进来,否则会出错

这里我们在添加边的时候,i->i-1和i-1->i这些边不要加进来,因为可以直接判断,所以总的边数最多就是50000条边
那么②和③在求最短路的时候直接从头到尾判断一次

刚开始是参考的大牛的代码(链接地址:http://blog.csdn.net/wangjian8006/article/details/7953886):

/*
Memory 948K
Time  219MS
*/

#include <iostream>
using namespace std;
#define MAXV 50002
#define INF INT_MAX
#define min(a,b) (a>b?b:a)
#define max(a,b) (a<b?b:a)

typedef struct{
	int s,t,w;
}Edge;

Edge edge[MAXV];
int n,d[MAXV],mi,ma;

void bellman_ford(){
	int i;
	bool flag=true;
	while(flag){
		flag=false;
		for(i=1;i<=n;i++){			//要使所有的点满足s[ai-1]-s[bi] <= -ci
			if(d[edge[i].t]>d[edge[i].s]-edge[i].w){
				d[edge[i].t]=d[edge[i].s]-edge[i].w;
				flag=true;
			}
		}
		
		for(i=mi;i<=ma;i++){		//要使所有点满足s[i]-s[i-1] <= 1
			if(d[i]>d[i-1]+1){
				d[i]=d[i-1]+1;
				flag=true;
			}
		}
		
		for(i=ma;i>=mi;i--){		//要使所有点满足s[i-1]-s[i] <= 0
			if(d[i-1]>d[i]){
				d[i-1]=d[i];
				flag=true;
			}
		}
	}
}

int main(){
	int i;
	while(~scanf("%d",&n)){
		mi=INF,ma=-1;
		for(i=1;i<=n;i++){
			scanf("%d%d%d",&edge[i].t,&edge[i].s,&edge[i].w);
			mi=min(mi,edge[i].t);		//找出源点与终点
			ma=max(ma,edge[i].s);
			edge[i].t--;				//使得ai-1
		}
		for(int i = 0; i < MAXV; i++)		//初始化
		{
			d[i] = 0;
		}
		bellman_ford();
		printf("%d\n",d[ma]-d[mi-1]);			//这里要包括最小点,所以是mi-1,否则会出错
	}
	return 0;
}

 

抱歉!评论已关闭.