题意:
第一行输入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
5 3 7 3 8 10 3 6 8 1 1 3 1 10 11 1
Sample Output
6
#include<stdio.h>
#include<string.h>
#include<vector>
#include<queue>
#define inf 1<<28
using namespace std;
#define MIN(a,b) a<b?a:b
#define MAX(a,b) a>b?a:b
struct 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;
}