Проверка на нечетные циклы в неориентированном графе - PullRequest
4 голосов
/ 03 декабря 2009

Я вернулся с другим похожим вопросом. В настоящее время я работаю над программой на Java, которая проверит, является ли граф 2-раскрашиваемым, то есть если он не содержит нечетных циклов (циклов длины нечетного числа). Предполагается, что весь алгоритм выполняется за O (V + E) времени (V - все вершины, а E - все ребра графа). Мой текущий алгоритм выполняет поиск в глубину, записывая все вершины на выбранном пути, затем ищет задний край и затем записывает, между какими вершинами находится край. Затем он отслеживает путь от одного конца заднего края до тех пор, пока не достигнет другой вершины на другом конце края, таким образом, возвращаясь к циклу, который завершает задний край.

У меня сложилось впечатление, что этот вид обхода может быть выполнен за O (V + E) время для всех циклов, которые существуют в моем графике, но я должен что-то упустить, потому что мой алгоритм работает смехотворно долго для очень больших графов (10 тыс. узлов, не знаю, сколько ребер).

Мой алгоритм полностью неверен? И если так, может ли кто-нибудь указать мне правильное направление для лучшего способа записи этих циклов или, возможно, сказать, есть ли у них нечетное количество вершин? Спасибо за любую помощь, которую вы, ребята, можете дать. Код ниже, если вам это нужно.

Дополнение: Извините, я забыл, если график не 2-цветный, мне нужно предоставить странный цикл, который доказывает, что это не так.

package algorithms311;

import java.util.*;
import java.io.*;

public class CS311 {

public static LinkedList[] DFSIter(Vertex[] v) {
    LinkedList[] VOandBE = new LinkedList[2];
    VOandBE[0] = new LinkedList();
    VOandBE[1] = new LinkedList();

    Stack stack = new Stack();

    stack.push(v[0]);
    v[0].setColor("gray");

    while(!stack.empty()) {
        Vertex u = (Vertex) stack.peek();
        LinkedList adjList = u.getAdjList();
        VOandBE[0].add(u.getId());

        boolean allVisited = true;
        for(int i = 0; i < adjList.size(); i++) {
            if(v[(Integer)adjList.get(i)].getColor().equals("white")) {
                allVisited = false;
                break;
            }
            else if(v[(Integer)adjList.get(i)].getColor().equals("gray") && u.getPrev() != (Integer)adjList.get(i)) {
                int[] edge = new int[2]; //pair of vertices
                edge[0] = u.getId(); //from u
                edge[1] = (Integer)adjList.get(i); //to v
                VOandBE[1].add(edge);
            }
        }
        if(allVisited) {
            u.setColor("black");
            stack.pop();
        }
        else {
            for(int i = 0; i < adjList.size(); i++) {
                if(v[(Integer)adjList.get(i)].getColor().equals("white")) {
                    stack.push(v[(Integer)adjList.get(i)]);
                    v[(Integer)adjList.get(i)].setColor("gray");
                    v[(Integer)adjList.get(i)].setPrev(u.getId());
                    break;
                }
            }
        }
    }
    return VOandBE;
}

public static void checkForTwoColor(String g) { //input is a graph formatted as assigned

    String graph = g;

    try {

        // --Read First Line of Input File
        // --Find Number of Vertices

        FileReader file1 = new FileReader("W:\\Documents\\NetBeansProjects\\algorithms311\\src\\algorithms311\\" + graph);
        BufferedReader bReaderNumEdges = new BufferedReader(file1);

        String numVertS = bReaderNumEdges.readLine();
        int numVert = Integer.parseInt(numVertS);

        System.out.println(numVert + " vertices");





        // --Make Vertices

        Vertex vertex[] = new Vertex[numVert];

        for(int k = 0; k <= numVert - 1; k++) {
            vertex[k] = new Vertex(k);
        }

        // --Adj Lists


        FileReader file2 = new FileReader("W:\\Documents\\NetBeansProjects\\algorithms311\\src\\algorithms311\\" + graph);
        BufferedReader bReaderEdges = new BufferedReader(file2);
        bReaderEdges.readLine(); //skip first line, that's how many vertices there are

        String edge;

        while((edge = bReaderEdges.readLine()) != null) {

            StringTokenizer ST = new StringTokenizer(edge);

            int vArr[] = new int[2];
            for(int j = 0; ST.hasMoreTokens(); j++) {
                vArr[j] = Integer.parseInt(ST.nextToken());
            }


            vertex[vArr[0]-1].addAdj(vArr[1]-1);
            vertex[vArr[1]-1].addAdj(vArr[0]-1);

        }

        LinkedList[] l = new LinkedList[2];

        l = DFSIter(vertex);//DFS(vertex);

        System.out.println(l[0]);



        for(int i = 0; i < l[1].size(); i++) {
            int[] j = (int[])l[1].get(i);
            System.out.print(" [" + j[0] + ", " + j[1] + "] ");
        }



        LinkedList oddCycle = new LinkedList();
        boolean is2Colorable = true;


        //System.out.println("iterate through list of back edges");

        for(int i = 0; i < l[1].size(); i++) { //iterate through the list of back edges
            //System.out.println(i);
            int[] q = (int[])(l[1].get(i)); // q = pair of vertices that make up a back edge
            int u = q[0]; // edge (u,v)
            int v = q[1];

            LinkedList cycle = new LinkedList();

            if(l[0].indexOf(u) < l[0].indexOf(v)) { //check if u is before v
                for(int z = l[0].indexOf(u); z <= l[0].indexOf(v); z++) { //if it is, look for u first; from u to v
                    cycle.add(l[0].get(z));
                }
            }
            else if(l[0].indexOf(v) < l[0].indexOf(u)) {
                for(int z = l[0].indexOf(v); z <= l[0].indexOf(u); z++) { //if it is, look for u first; from u to v
                    cycle.add(l[0].get(z));
                }
            }



            if((cycle.size() & 1) != 0) { //if it has an odd cycle, print out the cyclic nodes or write them to a file

                is2Colorable = false;

                oddCycle = cycle;

                break;
            }
        }
        if(!is2Colorable) {
            System.out.println("Graph is not 2-colorable, odd cycle exists");
            if(oddCycle.size() <= 50) {
                System.out.println(oddCycle);
            }
            else {
                try {
                    BufferedWriter outFile = new BufferedWriter(new FileWriter("W:\\Documents\\NetBeansProjects\\algorithms311\\src\\algorithms311\\" + graph + "OddCycle.txt"));
                    String cyc = oddCycle.toString();
                    outFile.write(cyc);
                    outFile.close();
                }
                catch (IOException e) {
                    System.out.println("Could not write file");
                }
            }
        }
    }
    catch (IOException e) {
        System.out.println("Could not open file");
    }
    System.out.println("Done!");
}

public static void main(String[] args) {
        //checkForTwoColor("smallgraph1");
        //checkForTwoColor("smallgraph2");
        //checkForTwoColor("smallgraph3");
        //checkForTwoColor("smallgraph4");
        checkForTwoColor("smallgraph5");

        //checkForTwoColor("largegraph1");
    }
}

Вершинный класс

package algorithms311;

import java.util.*;

public class Vertex implements Comparable {

    public int id;
    public LinkedList adjVert = new LinkedList();
    public String color = "white";
    public int dTime;
    public int fTime;
    public int prev;
    public boolean visited = false;

    public Vertex(int idnum) {
        id = idnum;
    }

    public int getId() {
        return id;
    }

    public int compareTo(Object obj) {
        Vertex vert = (Vertex) obj;
        return id-vert.getId();
    }

    @Override public String toString(){
        return "Vertex # " + id;
    }

    public void setColor(String newColor) {
        color = newColor;
    }

    public String getColor() {
        return color;
    }

    public void setDTime(int d) {
        dTime = d;
    }

    public void setFTime(int f) {
        fTime = f;
    }

    public int getDTime() {
        return dTime;
    }

    public int getFTime() {
        return fTime;
    }

    public void setPrev(int v) {
        prev = v;
    }

    public int getPrev() {
        return prev;
    }

    public LinkedList getAdjList() {
        return adjVert;
    }

    public void addAdj(int a) { //adds a vertex id to this vertex's adj list
        adjVert.add(a);
    }

    public void visited() {
        visited = true;
    }

    public boolean wasVisited() {
        return visited;
    }
}

Ответы [ 2 ]

4 голосов
/ 03 декабря 2009

У меня сложилось впечатление, что этот вид обхода может быть выполнен за O (V + E) время для всех циклов, которые существуют в моем графике

Может быть намного больше циклов, чем O (V + E) на графике. Если вы выполните итерацию всех из них, вы будете работать долго.

Возвращаясь к своей первоначальной идее, вы можете просто попытаться реализовать простой алгоритм для раскраски графа в два цвета (пометить произвольный узел как черный, все соседи в белом, все их соседи в черном и т. Д .; -первый поиск). Это действительно сделано во время O (V + E). Если вам это удастся, то график 2-раскраски. Если не получится, это не так.

Редактировать: Если вам нужен цикл, который доказывает, что граф не 2-раскрашивается, просто запишите для каждого узла вершину, из которой вы прошли в него. Когда вы переходите от черной вершины A к черной вершине B (таким образом, вам нужно раскрасить черный B в белый и доказать, что ваш график не является 2-цветным), вы получаете цикл, оглядываясь на родителей:

X -> Y -> Z -> U -> V -> P -> Q -> A 
                     \-> D -> E -> B

Тогда A-B-E-D-V-P-Q (путь к их общему предку) - это цикл, который вам нужен.

Обратите внимание, что в этой версии вам не нужно проверять все циклов, вы просто выводите первый цикл, где у задней кромки дерева обе вершины окрашены в один и тот же цвет.

2 голосов
/ 12 декабря 2009

вы описываете двудольный граф. двудольный граф имеет 2 раскраски и не содержит циклов нечетной длины. Вы можете использовать BFS, чтобы доказать, что граф является двудольным или нет. Надеюсь, это поможет.

...