/* $Id$ */ /* "Rete di scuole" (IOI 1996) Copyright (C) 2000 Massimo Santini This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* In questo programma implementiamo soltanto il calcolo della cardinalita` di un dominatore minimale. A tale scopo, rappresentiamo il grafo mediante una matrice di adiacenza A di dimensione NxN contenente in posizione (i,j) un 1 sse (i,j) e` un arco del grafo. Per trovare i nodi raggiungibili da un nodo dato usiamo una visita in profondita`, a tale scopo con il vettore visto[1..N] memorizziamo i nodi che la visita ha gia` visitato. In fine, con dominato[1..N] ricordiamo i nodi raggiungibili da qualche nodo gia` esaminato (dominato[i] contiene un 1 sse i e` dominato) e con D[1..N] ricordiamo il dominatore massimale (D[i] contiene un 1 sse i appartiene al dominatore). */ #include #define MAXN 100 int N, /* il numero di nodi */ A[MAXN][MAXN], /* la matrice di adiacenza */, visto[MAXN], /* il vettore caratteristico dei nodi visitati */ dominato[MAXN], /* il vettore caratteristico dei nodi dominati */ D[MAXN]; /* il vettore caratteristico dell'insieme dominatore */ /* Questa procedura legge l'input secondo il formato specificato */ void input( void ) { int i, j; scanf( "%d\n", &N ); for ( i = 0; i < N; i++ ) do { scanf( "%d", &j ); if ( j > 0 ) A[i][j-1] = 1; } while ( j > 0 ); } /* Questa procedura ricorsiva trova tutti i nodi raggiungibili da i e li aggiunge ai nodi dominati e li elimina dal insieme dominatore. Usa il vettore visto per controllare la ricorsione e non tornare a visitare nodi gia` esplorati. */ void visita( int i ) { int j; visto[i] = 1; dominato[i] = 1; D[i] = 0; for ( j = 0; j < N; j++ ) if ( A[i][j] && !visto[j] ) visita( j ); } /* Questa procedura inizializza il vettore visto ed esegue quindi la visita su i */ void aggiorna( int i ) { int j; for ( j = 0; j < N; j++ ) visto[j] = 0; visita( i ); } /* Il programma principale che contiene il ciclo fondamentale */ int main( void ) { int i, M; input(); /* leggiamo la matrice */ do { /* cerchiamo un nodo non dominato */ for ( i = 0; i < N; i++ ) if ( !dominato[i] ) break; /* se esco con i < N sono uscito grazie al break, quindi i e` un nodo non dominato, altrimenti sono uscito per la condizione di terminazione del for, e non ci sono pił nodi non dominati */ if ( i < N ) { aggiorna( i ); D[i] = 1; /* aggiungo in fine i all'insieme dominatore */ } } while ( i < N ); /* conto gli 1 in D, ossia la dimensione del dominatore*/ for ( i = 0, M = 0; i < N; i++ ) if ( D[i] ) M++; printf( "%d\n", M ); return 0; }