JZ高中OJ 1388. 自行车赛

Description

  翠亨村举行一场自行车赛,翠亨村有N个路口(编号1到N),另有M条双向边连接起来。下面有几个定义:
  •路径:由一系列边组成,满足后一条边的起点为前一条边的终点;
  •简单路径:每个路口最多经过一次的路径;
  •环:起点和终点在同一个路口的简单路径。
  保证每对路口之间至少有一条路径相连,除此之外还满足每条边最多只会出现在一个环中。
  你的任务是找出最长的满足以下两个条件的路径:
  •起点可以在任意路口,但终点必须在1号路口;
  •路径可能多次经过同一个路口,但每条边最多只会经过一次。
 

Input

  第一行包含两个整数N和M(2<=N<=10000,1<=M<=2N-2),表示路口数量和边的数量。
  接下来M行,每行包含两个不同的整数A和B(1<=A,B<=N),表示A和B之间存在一条边直接相连,两个路口之间最多只有一条边直接相连。

Output

  输出最长的比赛路径的长度。

 

Sample Input

输入1:
4 3
1 2
1 3
2 4

输入2:
6 6
1 2
1 3
2 4
3 4
3 5
5 6

输入3:
5 6
1 2
2 3
3 4
4 5
5 3
3 1

Sample Output

输出1:
2

输出2:
5

输出3:6
program staza;
uses Classes;
const MAXN = 10000;
const PUT = 0;
const DJIR = 1;
var
   n, m : longint;
   i : longint;
   a, b : longint;
   adj : array[1..MAXN] of TList;
   nPrstena : longint;
   broj : array[1..MAXN] of longint;
   prsten : array[1..MAXN] of TList;
   stack : array[1..MAXN] of longint;
   stackTop : longint;
   prsteni : array[1..MAXN] of TList;
   mostovi : array[1..MAXN] of TList;
   traversalTime : longint;
   discover : array[1..MAXN] of longint;
   lowlink : array[1..MAXN] of longint;
   memo : array[1..MAXN,0..1] of longint;
procedure dfs( u, dad : longint );
var
   i, v : longint;
begin
   traversalTime := traversalTime + 1;
   discover[u] := traversalTime;
   lowlink[u] := discover[u];
   stackTop := stackTop + 1;
   stack[stackTop] := u;
   for i := 0 to adj[u].Count-1 do begin
      v := longint(adj[u].Items[i]);
      if v = dad then continue;
      if discover[v] <> 0 then begin
         if discover[v] < lowlink[u] then lowlink[u] := discover[v];
      end else begin
         dfs( v, u );
         if lowlink[v] < discover[u] then begin
            if lowlink[v] < lowlink[u] then lowlink[u] := lowlink[v];
         end else if lowlink[v] = discover[u] then begin
            nPrstena := nPrstena + 1;
            prsten[nPrstena] := TList.Create;
            while stack[stackTop] <> v do begin
               prsten[nPrstena].Add( Pointer( broj[stack[stackTop]] ) );
               stackTop := stackTop-1;
            end;
            prsten[nPrstena].Add( Pointer( broj[stack[stackTop]] ) );
            stackTop := stackTop-1;
            prsteni[u].Add( Pointer( broj[nPrstena] ) );
         end else begin
            mostovi[u].Add( Pointer( broj[stack[stackTop]] ) );
            stackTop := stackTop-1;
         end;
      end;
   end;
end;
function max( a, b : longint ) : longint;
begin
   if a > b then max := a else max := b;
end;
function rec( X, stoRacunam : longint ) : longint;
var
   profit : longint;
   P : longint;
   best, smjer1, smjer2, ciklus : longint;
   i, j : longint;
begin
   if memo[X][stoRacunam] >= 0 then begin
      rec := memo[X][stoRacunam];
   end else begin
      memo[X][stoRacunam] := 0;
      profit := 0; (* koliko maksimalno mogu profitirati ako se ne moram vratiti u X *)
      for i := 0 to mostovi[X].Count-1 do begin (* za sve mostove koji izlaze iz X *)
         profit := max( profit, 1 + rec( longint(mostovi[X].Items[i]), PUT ) );
      end;
      for i := 0 to prsteni[X].Count-1 do begin (* za sve prstene koji vise iz X *)
         P := longint(prsteni[X].Items[i]);
         best := 0;
         smjer1 := 1; smjer2 := 1;
         ciklus := prsten[P].Count + 1;
         for j := 0 to prsten[P].Count-1 do begin
            best := max( best, smjer1 + rec( longint(prsten[P].Items[j]), PUT ) );
            smjer1 := smjer1 + 1 + rec( longint(prsten[P].Items[j]), DJIR );
            best := max( best, smjer2 + rec( longint(prsten[P].Items[prsten[P].Count-j-1]), PUT ) );
            smjer2 := smjer2 + 1 + rec( longint(prsten[P].Items[prsten[P].Count-j-1]), DJIR );
            ciklus := ciklus + rec( longint(prsten[P].Items[j]), DJIR );
         end;
         memo[X][stoRacunam] := memo[X][stoRacunam] + ciklus;
         profit := max( profit, best - ciklus );
      end;
      if stoRacunam = PUT then memo[X][stoRacunam] := memo[X][stoRacunam] + profit;
      rec := memo[X][stoRacunam];
   end;
end;
begin
   readln( n, m );
   for i := 1 to n do begin
      adj[i] := TList.Create;
      mostovi[i] := Tlist.Create;
      prsteni[i] := Tlist.Create;
      broj[i] := i;
   end;
   for i := 1 to m do begin
      readln( a, b );
      adj[a].Add( Pointer( broj[b] ) );
      adj[b].Add( Pointer( broj[a] ) );
   end;
   traversalTime := 0;
   for i := 1 to n do discover[i] := 0;
   stackTop := 0;
   nPrstena := 0;
   dfs( 1, 0 );
   for i := 1 to n do begin
      memo[i,0] := -1;
      memo[i,1] := -1;
   end;
   writeln( rec( 1, 0 ) );
end.

猜你喜欢

转载自www.cnblogs.com/anbujingying/p/11316554.html