int j;
for(i=0;i<n;i++)
{ fscanf(f,"%d",&ob[i].number);
fscanf(f,"%d",&ob[i].degree); //номер и степень
if(ob[i].degree!=0){
ob[i].nears=(int*)calloc(ob[i].degree,sizeof(int)); //создаем список смежности
for(j=0;j<ob[i].degree;j++)
fscanf(f,"%d",&ob[i].nears[j]);
};
}
return 1;
}
void clearmem(){ //очистка памяти
free(ob);
free(mark);
destroy_stack(&cicles);
destroy_stack(&st);
}
void clear(){ //очистка марок
for(int i=0;i<n;i++)
mark[i]=0;
}
int find_vertex(){ //находим вершину, с которой начинается обход
for(int i=0;i<n;i++)
if(mark[i]==0) return i;
return -1;
}
void is_able(int numb,int numbto){ //проверка достижимости numbto из numb. Используется при проверке достижимости вершин, которые были в цикле самих из себя
if(numb==numbto&&f==0) f=1; //если не первый раз столкнулись, то все
if(mark[numb]==0&&f!=1){ //если еще не проходили, текущую вершину и еще не нашли нужную вершину
if(numbto==numb) f=0; //инициализация переменной поиска. Первый раз при первом вызове
mark[numb]=1; //пометим текущую вершину как пройденную
for(int i=0;i<ob[numb].degree&&f!=1;i++)
is_able(ob[numb].nears[i],numbto); //дальше выполняем обход, если еще не нашли нужную вершину
}
}
void goth(int numb){ //классический обход в глубину
if(mark[numb]==0){
in_stack(&st,numb); //сохраняем путь в стек
mark[numb]=1;
for(int i=0;i<ob[numb].degree;i++)
goth(ob[numb].nears[i]);
}
else{
int i; //если встретились с уже пройденной вершиной, то пишем содержимое стека в хранилище.
for(i=0;i<st.head;i++)
if(!is_instack(cicles,st.data[i])) in_stack(&cicles,st.data[i]); //только если их там еще нет
}
}
int find_vercicles(){ //построение списка вершин, которые состоят в цикле
int from;
while((from=find_vertex())!=-1){ //ищем откуда
goth(from);
st.head=0;
};
if(is_empty(cicles)) return 0; //если не нашли, то 0
return 1;//иначе 1
}
void check_vers(){ //проверяем, что будет после удаления вершин
int i,j;
int but,nowver;
result=(int*)calloc(n,sizeof(int)); //выделим память
for(i=0;i<cicles.head;i++)
{
nowver=cicles.data[i]; //берем вершину из стека
but=1;
for(j=0;j<cicles.head&&but;j++) //и смотрим, будут ли остальные образовывать цикл
if(i!=j){
f=2;
clear();
mark[nowver]=2;
is_able(cicles.data[j],cicles.data[j]);
if(f==1) but=0;}
if(but){ //если нет, то пишем в результат
result[numbs_res]=nowver;
numbs_res++;
}
}
}
void output(){ //вывод
if(numbs_res==0) printf("No such vertexes.\n");
else{
int i;
printf("Such vertexes are\n");
for(i=0;i<numbs_res;i++)
printf("%d ",result[i]);
}
}
int main(){
if(input()==0) return 0;//ввод
clear();//очистка
create_stack(&cicles,n); //создадим хранилища
create_stack(&st,n);
if(!find_vercicles()) {printf("No cicles. Check input data.\n");return 0;} //строим список вершин
check_vers(); //проверяем, какие из них удовлетворяют условию
output(); //выводим
clearmem(); //очищаем память
getch();
return 1;
}
7)Тесты
№ |
Входные данные |
Рисунок графа |
Результат |
Примечание |
1 |
3 0 2 1 2 1 2 0 2 2 2 0 1 |
No such vertexes. |
В любом случае остаются циклы |
|
2 |
3 0 1 1 1 1 2 2 1 0 |
Such vertexes are 0 1 2 |
Простой цикл. При удалении однлй из вершин орграф становится ациклическим. |
|
3 |
4 0 1 1 1 2 2 3 2 1 0 3 1 0 |
Such vertexes are 0 1 |
Два цикла с общими вершинами, которые на стыке удовлетворяют условию |
|
4 |
6 0 1 1 1 1 2 2 1 0 3 1 4 4 1 5 5 1 3 |
No such vertexes. |
Циклы в разных компонентах сваязности |
|
5 |
4 0 1 1 1 1 2 2 1 0 3 1 0 |
Such vertexes are 0 1 2 |
Одна из вершин не влияет на циклы в орграфе |
|
6 |
1 0 |
Atomic graph |
Атомарный граф |
Программа полностью удовлетворяет предъявленным ей требованиям. На всех тестах программа показывает правильный результат.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.