poj 1716 Integer Intervals 差分约束系统

题意:给出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.


你可能感兴趣的:(poj 1716 Integer Intervals 差分约束系统)