题意:给出n个区间,现在要你找出一个点集,使得这n个区间都至少有2个元素在这个点集里面,问这个点集最少有几个点。
分析:这题跟poj 1201基本上是一个题。但这题据说还能用贪心做,在这里就不多加讨论了(正解才是王道!!!)。
这题其实就是差分约束系统的裸题。
那么我们先设若选了第i个数则ti为1否则为0,Si=t1+t2+...+ti
首先找到所有的约束关系:
很明显的一组约束关系就是Sb-S(a-1)>=2
但是若仅仅就这一组约束关系的话显然是不够的,那么根据S的性质很容易得到:
S(i+1)-Si>=0
Si-S(i-1)>=-1
那么对于一组约束条件x-y>=k,我们可以连一条y->x权值为k的边,那么从0开始跑最长路,d[max_num]就是答案啦。
注意要写spfa,bellman会TLE。
代码:
const maxn=60000; var v:array[0..maxn] of boolean; state:array[1..maxn*20] of longint; last,d:array[0..maxn] of longint; side:array[1..maxn*5] of record x,y,z,next:longint end; e,s,t:longint; procedure add(x,y,z:longint); begin inc(e); side[e].x:=x; side[e].y:=y; side[e].z:=z; side[e].next:=last[x]; last[x]:=e; end; procedure init; var n,i,x,y,z:longint; begin readln(n); s:=maxlongint; t:=0; for i:=1 to n do begin readln(x,y); if x<s then s:=x; if y+1>t then t:=y+1; add(x,y+1,2); end; for i:=s to t-1 do begin add(i,i+1,0); add(i+1,i,-1); end; end; procedure spfa; var i,u,head,tail:longint; begin for i:=s+1 to t do d[i]:=-maxlongint; fillchar(v,sizeof(v),true); v[s]:=false; head:=0; tail:=1; state[1]:=s; repeat inc(head); u:=state[head]; i:=last[u]; while i>0 do with side[i] do begin if d[x]+z>d[y] then begin d[y]:=d[x]+z; if v[y] then begin v[y]:=false; inc(tail); state[tail]:=y; end; end; i:=next; end; v[u]:=true; until head>=tail; writeln(d[t]); end; begin init; spfa; end.