Território de um vértice

Esta página introduz o conceito de território de um vértice num digrafo.  O conceito é simples e bem conhecido, mas o termo "território" não é muito usado.

Território

Um vértice x é acessível a partir de um vértice r se existe um passeio de rx.  O território de um vértice r é o conjunto de todos os vértices acessíveis a partir de r.  Se X é o território de um vértice então nenhum arco sai de X:  não existe arco com ponta inicial em X e ponta final fora de X.

Problema do território:  Dado um vértice r de um digrafo, encontrar o território de r.

Exercício

  1. [Importante]  Qual a relação entre os territórios de dois vértices diferentes?

Algoritmo do território

Eis uma primeira tentativa de solução do problema do território. O algoritmo abaixo pinta de preto todos os vértices do território de um vértice r. O digrafo tem vértices 1, …, n e conjunto A de arcos.

Rascunho-I (n, A, r)
1 o para  u ← 1  até  n  faça
2 oooo cor[u] ← branco
3 o cor[r] ← preto
4 o enquanto existe uv em A tal que cor[u] = preto e cor[v] = branco
5 oooo faça  cor[v] ← preto
6 o devolva  cor[1..n]

O algoritmo está correto, mas não é claro como executar a linha 4 de maneira eficiente. Para enfrentar essa dificuldade, vamos introduzir uma cor intermediária entre o branco e o preto.  Quando um vértice é visitado pela primeira vez, ele se torna cinza. O vértice permanece cinza enquanto seus vizinhos não tiverem sido todos visitados. Só depois que todos os vizinhos do vértice tiverem cor cinza, o vértice fica preto.  Para colocar essa ideia em prática, convém que o digrafo seja representado por suas listas de adjacência Adj[1..n] e não por seu conjunto de arcos.

Rascunho-II (n, Adj, r)
o para  u ← 1  até  n  faça
oooo cor[u] ← branco
o cor[r] ← cinza
o enquanto existe  u  tal que  cor[u] = cinza  faça
oooo para cada  v  em  Adj[u]  faça
ooooooo se  cor[v] = branco
oooooooooo então  cor[v] ← cinza
oooo cor[u] ← preto
o devolva  cor[1..n]

No fim da execução do algoritmo, todo vértice é branco ou preto. Um vértice v está no território de r se e somente se cor[v]= preto.

No início de cada iteração do bloco de linhas 5-8, o conjunto dos vértices cinza "separa" os vértices pretos dos brancos. Mais precisamente,

  1. não existe arco xy tal que x é preto e y é branco  e
  2. para todo vértice cinza y distinto de r, existe um arco xy tal que x é preto;
  3. todo arco com uma ponta preta tem a outra ponta preta ou cinza.

A propriedade i afirma que a região cinza separa a região preta da branca. De acordo com a propriedade ii, a região cinza está na fronteira da região preta.

A forma do Rascunho-II não é inteiramente satisfatória, pois ainda não está claro como implementar a linha 4. Uma implementação eficiente deve reunir os vértices cinza em algum tipo de lista de onde um vértice possa ser rapidamente retirado e à qual um novo vértice possa ser rapidamente acrescentado.  Nosso rascunho adquire então a seguinte forma final:

  Território (n, Adj, r)
1o para  u ← 1  até  n  faça
1oooo cor[u] ← branco
1o cor[r] ← cinza
1o LCria-Lista(r)
1o enquanto  L  não estiver vazia faça
1oooo uRetira-da-Lista(L)
1oooo para cada  v  em  Adj[u]  faça
1ooooooo se  cor[v] = branco
1oooooooooo então  cor[v] ← cinza
10  oooooooooo então  Insere-na-Lista(v, L)
11  oooo cor[u] ← preto
12  o devolva  cor[1..n]

O comando Cria-Lista(r) cria uma lista de vértices tendo r como único elemento.  O comando Retira-da-Lista(L) retira um vértice da lista L.  O comando Insere-na-Lista(v,L) insere v em L.  No início de cada repetição do bloco de linhas 6-11, um vértice é

[A linha 6 do código tem um caráter não determinístico, pois dá ao algoritmo a liberdade de escolher qualquer vértice u da lista.  Algumas pessoas ficam incomodadas com esse não determinismo. Mas não há razão alguma para o desconforto, pois o algoritmo funciona corretamente como quer que u seja escolhido.  Comentário análogo pode ser feito sobre da escolha de v na linha 7.]

Exercícios

  1. Dê uma cota superior (em notação Ο) para o consumo de tempo do Rascunho-I.  Suponha que a linha 4 é implementada da maneira mais literal possível.
  2. Dê uma cota superior (em notação Ο) para o consumo de tempo do Rascunho-II.  Suponha que a linha 4 é implementada da maneira mais literal possível.
  3. [Interessante]  Mostre que a lista de vértices do algoritmo Território torna a cor cinza supérflua.  [Solução]

Consumo de tempo do algoritmo Território

Quanto tempo o algoritmo Território consome no pior caso? Vamos medir esse tempo em relação ao tamanho do digrafo, ou seja, em relação ao número n de vértices e ao número m de arcos do digrafo.  Vamos supor que cada uma das funções que manipula a lista de vértices — Cria-Lista, Retira-da-Lista e Insere-na-Lista — consome tempo constante, ou seja, consome uma quantidade de tempo que não depende de nm.

O tempo gasto com as operações de inicialização nas linhas 1-4 não passa de  Ο(n) .   Quanto ao bloco linhas 6-11, é melhor não tentar estimar, em separado, o número de iterações do bloco e o tempo gasto com cada iteração. É melhor estimar o tempo total gasto com cada linha dentro desse bloco.  (Imagine que o algoritmo cobra R$1 para executar cada linha e conte a quantia total gasta no fim.)

Conclusão: o consumo de tempo do algoritmo Território é

Ο(n+m) .

O algoritmo é, portanto, linear.

Poderíamos ser mais precisos e dizer que o consumo de tempo é  Ο(n′+m′),  sendo n′ o número de vértices no território de r e m′ o número de arcos que têm ambas as pontas no território de r.  Mais ainda: como m′ ≥ n′−1, podemos dizer o consumo de tempo é simplesmente Ο(m′).

Exercícios

  1. [Bom!]  Escreva uma versão do algoritmo Território para um digrafo com vértices 1, 2, … , n representado por sua matriz de adjacência.  Mostre que o consumo de tempo dessa versão é  Ο(n2).

Valid HTML 4.01 Strict Valid CSS!