jzoj 1277. 最高的奶牛

Description

  FJ有N(1 <= N <= 10,000)头奶牛,编号为1到N,站成一条直线。每头奶牛自己的身高(正整数,秘密未知),告诉你最高奶牛的身高H及位置I,同时告诉你R(0 <= R <= 10,000)组信息,每组信息由两个数ai,bi组成,表示奶牛ai可以看到奶牛bi,这就意味着奶牛bi的身高至少和奶牛ai的身高一样高,同时奶牛ai到奶牛bi之间的奶牛身高必须低于奶牛ai
  现在要你求出每头奶牛最高可能的高度,保证有解。

Input

  第1行输入4个空格隔开的整数N,I,H,R
  第2到R+1行,每行两个空格隔开的不同的整数A,B(1<=A,B<=N),表示奶牛A能看到奶牛B

Output

  第1到N行,每行一个整数表示每只奶牛最高可能的高度。

Sample Input

9 3 5 5
1 3
5 3
4 3
3 7
9 8

Sample Output

5
4
5
3
4
4
5
5
5

Data Constraint

Hint

解释:如果奶牛A和奶牛B一样高,则可以出现A看到B,B又看到A的情况,如果奶牛A矮于奶牛B,则只可能出现奶牛A看到奶牛B,奶牛B不可能看到奶牛A。

分析:这道题的数据太水了。有提议得,对于任意一对i,j,显然有
Hi<=Hj Hk

type
 node=record
  y,w,next:longint;
 end;

var
 h:array [1..10000] of longint;
 g:array [1..5000000] of node;
 ls,r,list:array [1..10000] of longint;
 n,ei,eh,l,i,j,x,y,m,head,tail,t,xx,yy:longint;

function min(x,y:longint):longint;
 begin
  if x<y then exit(x)
         else exit(y);
 end;

function find(x,y:longint):boolean;
var t:longint;
 begin
  t:=ls[x];
  while t>0 do
   begin
    if g[t].y=y then exit(true);
    t:=g[t].next;
   end;
  exit(false);
 end;

procedure add(x,y,w:longint);
 begin
  inc(m);
  g[m].y:=y;
  g[m].w:=w;
  g[m].next:=ls[x];
  ls[x]:=m;
 end;
begin
 readln(n,ei,eh,l);
 for i:=1 to n do
  h[i]:=eh;
 for i:=1 to l do
  begin
   readln(x,y);
   if find(x,y) then continue;
   add(y,x,0);
   r[x]:=r[x]+1;
   xx:=x; yy:=y;
   if x>y then begin xx:=y; yy:=x; end;
   for j:=xx+1 to yy-1 do
    begin
     add(x,j,1);
     r[j]:=r[j]+1;
    end;
  end;
 for i:=1 to n do
  if r[i]=0 then
   begin
    inc(tail);
    list[tail]:=i;
   end;
 repeat
  inc(head);
  t:=ls[list[head]];
  x:=list[head];
  while t>0 do
   begin
    y:=g[t].y;
    dec(r[y]);
    if r[y]=0 then
     begin
      inc(tail);
      list[tail]:=y;
     end;
    h[y]:=min(h[y],h[x]-g[t].w);
    t:=g[t].next;
   end;
 until head=tail;
 for i:=1 to n do
  writeln(h[i]);
end.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值