[题目来源]:POJ1201
[关键字]:差分约束系统
[题目大意]:有n个区间 ,已知每个区间至少有多少点问满足所有条件的最小点数。
//=====================================================================================================
[分析]:/*设s[i]为前从1到i有几个点,则可写出不等式:s[ed]-s[st-1]>=a,a就是要求的每个区间的至少有多少。同时为了将所有点连成一个图,还需要一个条件:s[i]-s[i-1]<=1。由此可以构建差分约束系统,从1开始求最短路即可。此题不可反向连边求最大路,因为:s[i]-s[i-1]<=1,如果求最大路会出现正权回路。*/以前对于差分约束系统理解不是很好,现在重新写一下。首先对于这道题可以写出不等式组:
s[i]-s[i-1]>=0 => s[i]-s[i-1]>=0
s[i]-s[i-1]<=1 => s[i-1]-s[i]>=-1
s[y]-s[x-1]>=c => s[y]-s[x-1]>=c
s[i]-s[s]>=0 => s[i]-s[s]>=0
然后连边spfa求解。具体连边可以参考http://www.cnblogs.com/procedure2012/archive/2012/03/14/2396254.html
[代码]:
View Code
1 type
2 rec = record
3 y, d, n: longint
4 end;
5 var
6 max, n, tot: longint;
7 e: array[0..600000] of rec;
8 link: array[0..600000] of longint;
9 q: array[0..300000] of longint;
10 b: array[0..600000] of boolean;
11 d: array[0..600000] of longint;
12
13 procedure make(x, y, d: longint);
14 begin
15 inc(tot);
16 e[tot].y := y;
17 e[tot].d := d;
18 e[tot].n := link[x];
19 link[x] := tot;
20 end;
21
22 procedure init;
23 var
24 i, x, y, d: longint;
25 begin
26 readln(n);
27 max := 0;
28 for i := 1 to n do
29 begin
30 readln(x,y,d);
31 make(y+1,x,-d);
32 if max < y+1 then max := y+1;
33 end;
34 for i := 0 to max do
35 begin
36 make(i,i+1,1);
37 make(i+1,i,0);
38 end;
39 end;
40
41 procedure spfa;
42 var
43 h, t, x, y, next: longint;
44 begin
45 h := 0;
46 t := 1;
47 fillchar(d,sizeof(d),100);
48 fillchar(b,sizeof(b),false);
49 b[max] := true;
50 q[1] := max;
51 d[max] := 0;
52
53 while h <> t do
54 begin
55 h := (h+1) mod 30000;
56 x := q[h];
57 next := link[x];
58 while next > 0 do
59 begin
60 y := e[next].y;
61 if d[x]+e[next].d < d[y] then
62 begin
63 d[y] := d[x]+e[next].d;
64 if not b[y] then
65 begin
66 t := (t+1) mod 30000;
67 q[t] := y;
68 b[y] := true;
69 end;
70 end;
71 next := e[next].n;
72 end;
73 b[x] := false;
74 end;
75 writeln(-d[1]);
76 //readln;
77 end;
78
79 begin
80 init;
81 spfa;
82 end.
全新代码(推荐)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int MAXN=51000;
struct node
{
int x,y,next,d;
}e[MAXN*4];
int first[MAXN];
int n,tot,m,s=51000;
int d[MAXN];
bool b[MAXN];
void Add(int x,int y,int d)
{
e[++tot].y=y;
e[tot].d=d;
e[tot].next=first[x];
first[x]=tot;
}
int SPFA()
{
queue<int> q;
memset(d,200,sizeof(d));
memset(b,0,sizeof(b));
d[s]=0,b[s]=1;
q.push(s);
while (!q.empty())
{
int u=q.front();
b[u]=0;
q.pop();
for (int i=first[u];i;i=e[i].next)
{
int v=e[i].y;
if (d[v]<d[u]+e[i].d)
{
d[v]=d[u]+e[i].d;
if (!b[v])
{
q.push(v);
b[v]=1;
}
}
}
}
return d[n];
}
int main()
{
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
scanf("%d",&m);
int x,y,z;
for (int i=1;i<=m;++i)
{
scanf("%d%d%d",&x,&y,&z);
Add(x-1,y,z);
if (y>n) n=y;
if (s>x-1) s=x-1;
}
for (int i=s+1;i<=n;++i)
{
Add(i-1,i,0);
Add(i,i-1,-1);
Add(s,i,0);
}
/*printf("%d %d\n",s,n);
for (int i=s;i<=n;++i)
for (int j=first[i];j;j=e[j].next)
printf("%d %d %d\n",i,e[j].y,e[j].d);*/
printf("%d\n",SPFA());
return 0;
}