#include<stdio.h> #include<string.h> #include<iostream> using namespace std; #define N 1000005 #define INF 999999999 int head[N], vis[N], queue[N], dis[N], outqueue[N]; int n, index; struct Edge { int v, value, next; }edge[N]; void add_Edge(int u, int v, int val) { edge[index].next=head[u]; edge[index].v=v; edge[index].value=val; head[u]=index++; } void Spfa(int s) { int iq=0, front=0, i, top; memset(vis, 0, sizeof(vis)); memset(outqueue, 0, sizeof(outqueue)); for(i=1; i<=n; i++) dis[i]=INF; dis[s]=0; queue[iq++]=s; vis[s]=1; while(iq!=front) { top=queue[front]; front++; vis[top]=0; outqueue[top]++; if(outqueue[top]>n) return ; for(i=head[top]; i!=-1; i=edge[i].next) { if(dis[top]+edge[i].value<dis[edge[i].v]) { dis[edge[i].v]=dis[top]+edge[i].value; if(vis[edge[i].v]==0) { vis[edge[i].v]=1; queue[iq++]=edge[i].v; } } } } } int main() { int nn, a, b, c, i, maxn; while(scanf("%d", &n)!=EOF) { maxn=0, index=0; memset(head, -1, sizeof(head)); for(i=0; i<n; i++) { scanf("%d%d%d", &a, &b, &c); maxn=max(maxn, b); add_Edge(a-1, b, -1*c); } for(i=1; i<=maxn; i++) { add_Edge(i, i-1, 1); add_Edge(i-1, i, 0); } n=maxn; Spfa(0); printf("%d ", -1*dis[maxn]); } return 0; }
题目链接:http://poj.org/problem?id=1201
题目大意:有一个集合,给出n个关系,每组关系三个数a, b, c代表[a, b]区间最少c个数。求出集合中做少有多少个数字
解题思路:[差分约束] 1.我们首先要转化成差分约束的特征形势x-y<=z的形势。
2.我们设ti表示i之前的区间有多少个数。那么tb-t(a-1)>=c ---(变形)--->t(a-1)-tb<=-c;
由于ti我们有合理的意义,那么0=<ti-t(i-1)<=1,即相邻两个数区间最多增加1个数 变形得到:ti-t(i-1)<=1 t(i-1)-ti<=0
3.组合上面的条件,得到差分约束系统。建图
4.用spfa算法求解最短路
5.由于t(a-1)-tb<=-c,c加了负号, 因此得出的结果要从负数变为整数
代码如下: