summaryrefslogtreecommitdiffstats
path: root/05-advanced_algorithms_and_complexity/03-np-completness/02-cleaning_apartment/cleaning_apartment.cpp
blob: a20515892b771cb80a5fa12850a0c048ab195b65 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include <bits/stdc++.h>
using namespace std;

struct Edge {
    int from;
    int to;
};

struct ConvertHampathToSat {
    int numVertices;
    vector<Edge> edges;

    ConvertHampathToSat(int n, int m) :
        numVertices(n),
        edges(m)
    {  }

    // matrix of vertices * vertices (+1 because 0 is reserved)
    static inline int var(int v1, int v2, int n) { return 1 + v1 * n + v2; }

    void printEquisatisfiableSatFormula() {
        vector<vector<int>> clauses;
        vector<int> cstrs;

        for (int i = 0; i < numVertices; i++) {
            // the vertex belongs to the path, matrix rows
            cstrs.clear();
            for (int j = 0; j < numVertices; j++)
                cstrs.push_back(var(i, j, numVertices));      // (Xi0 || Xi1 || Xi2 ...)
            clauses.push_back(cstrs);

            // the vertex appears just once in the path
            for (int j = 0; j < numVertices; j++) {
                for (int k = j + 1; k < numVertices; k++)
                    clauses.push_back({-var(i, j, numVertices), -var(i, k, numVertices)});  // ( !Xij && !Xik )
            }

            // each position in the path has a vertex, matrix cols
            cstrs.clear();
            for (int j = 0; j < numVertices; j++)
                cstrs.push_back(var(j, i, numVertices));      // (X0i || X1i || X2i ...)
            clauses.push_back(cstrs);

            // each position has only 1 vertex
            for (int j = 0; j < numVertices; j++) {
                for (int k = j + 1; k < numVertices; k++)
                    clauses.push_back({-var(j, i, numVertices), -var(k, i, numVertices)});  // ( !Xji && !Xki )
            }

            // if there is no ij edje, there is no Xik Xj(k+1) or Xjk Xi(k+1)
            for (int j = i + 1; j < numVertices; j++) {
                // would be much faster with an adjacent matrix
                bool found = false;
                for (Edge e : edges) {
                    if ((e.from == i+1 && e.to == j+1) || (e.from == j+1 && e.to == i+1)) {
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    // no v-w edge
                    for (int k = 0; k < (numVertices - 1); k++) {
                        clauses.push_back({-var(i, k, numVertices), -var(j, k + 1, numVertices)});  // ( !Xik && !Xj(k+1)
                        clauses.push_back({-var(j, k, numVertices), -var(i, k + 1, numVertices)});  // ( !Xjk && !Xi(k+1)
                    }
                }
            }
        }

        cout << clauses.size() << " " << numVertices * numVertices << endl;
        for (vector<int>& c : clauses) {
            for (int v : c) {
                cout << v << " ";
             }
             cout << "0" << endl;
        }
        cout << endl;
    }
};

int main() {
    ios::sync_with_stdio(false);

    int n, m;
    cin >> n >> m;
    ConvertHampathToSat converter(n, m);
    for (int i = 0; i < m; ++i) {
        cin >> converter.edges[i].from >> converter.edges[i].to;
    }

    converter.printEquisatisfiableSatFormula();

    return 0;
}