Invertire il grafo#10048

Invertire il grafo (Editoriale)

Costruiamo un grafo 0 - 1, assegnando agli archi esistenti il peso , e ai loro archi inversi il peso . Successivamente eseguiamo una ricerca in ampiezza. La lunghezza del cammino più breve dal vertice al vertice sarà uguale al numero minimo di archi che devono essere invertiti.

Esempio

Il grafo riportato nell'esempio si presenta come segue:

Implementazione dell'algoritmo

Dichiariamo una costante infinito.

#define INF 0x3F3F3F3F

Dichiariamo l'array delle distanze minime e la lista di adiacenza del grafo . Per ogni arco, insieme al vertice adiacente, memorizziamo il peso dell'arco ( o ).

vector<int> dist;
vector<vector<pair<int, int> > > g;

La funzione bfs implementa la ricerca in ampiezza a partire dal vertice .

void bfs(int start)
{
  dist = vector<int>(n + 1, INF);
  dist[start] = 0;

  deque<int> q;
  q.push_back(start);

  while (!q.empty())
  {
    int v = q.front(); q.pop_front();
    for (auto edge : g[v])
    {
      int to = edge.first;
      int w = edge.second;
      if (dist[to] > dist[v] + w)
      {
        dist[to] = dist[v] + w;

A seconda del peso dell'arco , aggiungiamo il vertice alla fine o all'inizio della coda.

        if (w == 1)
          q.push_back(to);
        else
          q.push_front(to);
      }
    }
  }
}

Parte principale del programma. Leggiamo i dati in ingresso.

scanf("%d %d", &n, &m);
g.resize(n + 1);
for (i = 0; i < m; i++)
{
  scanf("%d %d", &a, &b);

All'arco orientato a → b assegniamo il peso , all'arco inverso assegniamo il peso .

  g[a].push_back({ b, 0 });
  g[b].push_back({ a, 1 });
}

Eseguiamo la ricerca in ampiezza a partire dal vertice .

bfs(1);

Stampiamo la risposta — la distanza minima fino al vertice .

if (dist[n] == INF)
  printf("-1\n");
else
  printf("%d\n", dist[n]);