Cod sursa(job #82723)

Utilizator gurneySachelarie Bogdan gurney Data 8 septembrie 2007 16:07:26
Problema Critice Scor 100
Compilator fpc Status done
Runda Arhiva de probleme Marime 5.25 kb
program critice;
  const
    fin='critice.in';
    fout='critice.out';
    nmax=1010;
    mmax=20020;
    inf=maxlongint shr 1;
type
  int=array[0..nmax] of integer;
  lint=array[0..nmax] of longint;
  tlint=^lint;
  tinteger=^int;
  mint=array[0..mmax] of integer;
  mlint=array[0..mmax] of longint;
  mtlint=^mlint;
  mtinteger=^mint;
var
  list:array[0..nmax] of record
    prev,next:integer;
    node:integer;
    end;
  target,prev,start:mint;
  e:mtlint;
  cap,act,tmp:integer;
  capa,flow:mlint;
  mc:array[0..mmax] of boolean;
  last,q,h,current:tinteger;
  used:array[0..nmax] of boolean;
  pop,push,m,cur,i,n,x,y,c,nedge:longint;
  tflow:longint;
  critic:array[0..nmax] of boolean;
  num:longint;

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

procedure insert(x,y,c:longint);
  begin
    inc(nedge);
    start[nedge]:=x;target[nedge]:=y;
    capa[nedge]:=c;flow[nedge]:=0;
    prev[nedge]:=last^[x];
    last^[x]:=nedge;
    inc(nedge);
    start[nedge]:=y;target[nedge]:=x;
    capa[nedge]:=c;flow[nedge]:=0;
    prev[nedge]:=last^[y];
    last^[y]:=nedge;
  end;

function op(n:integer):integer;
  begin
    if n and 1=1 then
      op:=n+1
    else
      op:=n-1;
  end;

procedure init_flow;
  begin
    new(last);new(q);
    fillchar(last^,sizeof(last^),0);
    new(e);
    fillchar(e^,sizeof(e^),0);
    new(h);
    fillchar(h^,sizeof(h^),0);
    h^[1]:=n;
    new(current);
  end;

procedure init_preflow;
  var
    cur:integer;
  begin
    e^[1]:=inf;
    cur:=last^[1];
    while cur>0 do
      begin
        e^[target[cur]]:=capa[cur];
        dec(e^[start[cur]],capa[cur]);
        flow[cur]:=capa[cur];
        flow[op(cur)]:=-capa[cur];
        cur:=prev[cur];
      end;
  end;

procedure ridica(x:integer);
  var
    min:integer;
    cur:integer;
  begin
    cur:=last^[x];
    min:=-1;
    while cur>0 do
      begin
        if flow[cur]<capa[cur] then
          if (min=-1)or(h^[target[cur]]<min) then
            min:=h^[target[cur]];
        cur:=prev[cur];
      end;
    h^[x]:=min+1;
  end;

procedure pompeaza(cur:integer);
  var
    delta:longint;
  begin
    if e^[start[cur]]<capa[cur]-flow[cur] then
      delta:=e^[start[cur]]
    else
      delta:=capa[cur]-flow[cur];
    inc(flow[cur],delta);
    dec(flow[op(cur)],delta);
    dec(e^[start[cur]],delta);
    inc(e^[target[cur]],delta);
  end;

procedure descarca(x:integer);
  var
    v:integer;
  begin
    while e^[x]>0 do
      begin
        v:=target[current^[x]];
        if current^[x]=0 then
          begin
            ridica(x);
            current^[x]:=last^[x];
          end
        else
          begin
            if (h^[x]=h^[target[current^[x]]]+1)and(flow[current^[x]]<capa[current^[x]]) then
              pompeaza(current^[x])
            else
              current^[x]:=prev[current^[x]];
          end;
      end;
  end;

begin
  assign(input,fin);
    reset(input);
    readln(n,m);
    nedge:=0;
    init_flow;
    for i:=1 to m do
      begin
        readln(x,y,c);
        insert(x,y,c);
      end;
  close(input);
  assign(output,fout);
    rewrite(output);
    init_preflow;
    for i:=1 to n-2 do
      with list[i] do
        begin
          node:=i+1;
          prev:=i-1;
          next:=i+1;
          current^[i+1]:=last^[i+1];
        end;
    list[1].prev:=0;
    list[n-2].next:=0;
    cap:=1;act:=1;
    while act>0 do
      begin
        x:=list[act].node;
        tmp:=h^[x];
        descarca(x);
        if (h^[x]>tmp)and(act<>cap) then
          begin
            list[list[act].prev].next:=list[act].next;
            list[list[act].next].prev:=list[act].prev;
            list[act].next:=cap;
            list[cap].prev:=act;
            cap:=act;
            list[cap].prev:=0
          end;
        act:=list[act].next;
      end;
      tflow:=e^[n];
    fillchar(used,sizeof(used),false);
    q^[1]:=1;pop:=1;push:=2;used[1]:=true;
    critic[1]:=true;
    while pop<push do
      begin
        cur:=q^[pop];
        inc(pop);
        x:=last^[cur];
        while x>0 do
          begin
            if (abs(flow[x])<capa[x]) and (not(used[target[x]])) then
              begin
                used[target[x]]:=true;
                q^[push]:=target[x];
                inc(push);
                critic[target[x]]:=true;
              end;
            x:=prev[x];
          end;
      end;
    fillchar(used,sizeof(used),false);
    q^[1]:=n;pop:=1;push:=2;used[n]:=true;
    while pop<push do
      begin
        cur:=q^[pop];
        inc(pop);
        x:=last^[cur];
        while x>0 do
          begin
            if (abs(flow[x])<capa[x]) and (not(used[target[x]])) then
              begin
                used[target[x]]:=true;
                q^[push]:=target[x];
                inc(push);
              end;
            x:=prev[x];
          end;
      end;
    num:=0;
    for i:=1 to nedge do
      if (critic[start[i]]) and (used[target[i]]) then
        begin
          inc(num);
          mc[(i+1)shr 1]:=true;
        end;
    writeln(num);
    for i:=1 to nedge do
      if mc[i] then
        writeln(i);
  close(output);
end.