Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * WIP Polynomial Time Algorithm: Given 2 Graphs, are they Isomorphic?
- * By Karim Ehab ElSheikh 2018-04-20
- */
- using namespace std;
- #include<bits/stdc++.h>
- int n1, n2, n;
- multiset<pair<int, int> > e1;
- multiset<pair<int, int> > e2;
- vector<int> g1[100];
- vector<int> g2[100];
- int z[100];
- bool matched[10000];
- vector<int> u1;
- vector<int> u2;
- set<pair<int,int> > tp1[100][100];
- set<pair<int,int> > tp2[100][100];
- multiset<int> t1[100][100];
- multiset<int> t2[100][100];
- bool visited[100];
- int m[20][100];
- int sol[20][100][100];
- int M[100];
- int invM[100];
- int maximumDepth;
- bool graph;
- //debug
- #define dump(x) cerr << #x << " = " << (x) << endl
- #define write(x) cerr << #x << " = " << (x) << ", "
- #define writeI0 cerr << "i = " << 0 << ", "
- #define dumpI0 cerr << "i = " << 0 << endl
- #define printArray(a,x,y) for(auto it = a+x; it != a+y; it++) (it==a+x)? cout << *it : cout << ' ' << *it; cout << endl
- #define printSet(s) if(s.size()==0) cout << "{}"; else for(auto it = s.begin(); it!=s.end(); it++) (it==s.begin())? cout << *it : cout << ' ' << *it; cout << endl
- #define printSet2(s) if(s.size()==0) cout << "{}"; else for(auto it = s.begin(); it!=s.end(); it++) (it==s.begin())? cout << *it : cout << ',' << *it;
- #define printPairSet(s) for(auto it = s.begin(); it!=s.end(); it++) (it==s.begin())? cout << '(' << it->first << ", " << it->second << ')' : cout << " (" << it->first << ", " << it->second << ')'; cout << endl
- #define printVector(x) for(auto it = x.begin(); it!=x.end(); it++) (it==x.begin())? cout << *it : cout << ' ' << *it; cout << endl
- int dfs(int i, bool grph) {
- visited[invM[i]] = true;
- int to, degree2, r = 0;
- if(!grph) {
- for(int j = 0; j < g1[i].size(); j++) {
- to = M[g1[i][j]];
- if(visited[to]) continue;
- r += dfs(to, grph) + 1;
- }
- }
- else {
- for(int j = 0; j < g2[i].size(); j++) {
- to = g2[i][j];
- if(visited[to]) continue;
- r += dfs(to, grph) + 1;
- }
- }
- return r;
- }
- void caculateMaximumDepth(int s, int e, bool graph) { // Largest Connected Component, Constant Factor Optimization
- int maximumPotentialDepth = e-s;
- maximumDepth = maximumPotentialDepth;
- for(int i = s; i <= e; i++)
- visited[i] = false;
- if(!graph) {
- for(int i = s; i <= e; i++)
- if(!visited[i])
- maximumDepth = min(maximumDepth, dfs(M[i], false));
- }
- else {
- for(int i = s; i <= e; i++)
- if(!visited[i])
- maximumDepth = min(maximumDepth, dfs(i, true));
- }
- }
- void clearTravellingTable(int s1, int e1, int s2, int e2) {
- caculateMaximumDepth(s1, e1, false);
- for(int i = s1; i <= e1; i++) {
- for(int j = 0; j <= maximumDepth; j++) {
- t1[i][j].clear();
- }
- }
- caculateMaximumDepth(s2, e2, true);
- for(int i = s2; i <= e2; i++) {
- for(int j = 0; j <= maximumDepth; j++) {
- t2[i][j].clear();
- }
- }
- }
- void buildTravellingTable(int s1, int e1, int s2, int e2) {
- u1.clear();
- for(int i = s1; i <= e1; i++) {
- u1.push_back(M[i]);
- tp1[i][0].insert(make_pair(M[i], g1[M[i]].size()));
- }
- for(int i = s2; i <= e2; i++) {
- tp2[i][0].insert(make_pair(i, g2[i].size()));
- }
- sort(u1.begin(), u1.end());
- int to, node, degree, degree2;
- caculateMaximumDepth(s1, e1, false);
- dump(maximumDepth);
- for(int i = s1; i <= e1; i++) {
- for(int j = 0; j < maximumDepth; j++) {
- for(auto it = tp1[i][j].begin(); it != tp1[i][j].end(); it++) {
- node = it->first;
- degree = it->second;
- for(int k = 0; k < g1[node].size(); k++) {
- if(!binary_search(u1.begin(), u1.end(), g1[node][k])) continue;
- to = g1[node][k];
- degree2 = degree + g1[to].size();
- tp1[i][j+1].insert(make_pair(to, degree2));
- }
- }
- }
- }
- caculateMaximumDepth(s2, e2, true);
- for(int i = s2; i <= e2; i++) {
- for(int j = 0; j < maximumDepth; j++) {
- for(auto it = tp1[i][j].begin(); it != tp2[i][j].end(); it++) {
- node = it->first;
- degree = it->second;
- for(int k = 0; k < g2[node].size(); k++) {
- if(g2[node][k] < s2 || g2[node][k] > e2) continue;
- to = g2[node][k];
- degree2 = degree + g2[to].size();
- tp2[i][j+1].insert(make_pair(to, degree2));
- }
- }
- }
- }
- for(int i = s1; i <= e1; i++) {
- for(int j = 0; j <= maximumDepth; j++) {
- for(auto it = tp1[i][j].begin(); it != tp1[i][j].end(); it++)
- t1[i][j].insert(it->second);
- for(auto it = tp2[i][j].begin(); it != tp2[i][j].end(); it++)
- t2[i][j].insert(it->second);
- }
- }
- }
- auto comp = [] (int x, int y) {
- int a, b, cmp;
- if(!graph) {
- for(int i = 0; i <= maximumDepth; i++) {
- for(auto it = t1[x][i].begin(); it != t1[x][i].end(); it++) {
- a = t1[x][i].count(*it);
- b = t1[y][i].count(*it);
- cmp = a - b;
- if(cmp < 0) return false;
- else if(cmp > 0) return true;
- }
- a = t1[x][i].size();
- b = t1[y][i].size();
- cmp = a - b;
- if(cmp < 0) return false;
- else if(cmp > 0) return true;
- }
- return true;
- }
- else {
- for(int i = 0; i <= maximumDepth; i++) {
- for(auto it = t1[x][i].begin(); it != t1[x][i].end(); it++) {
- a = t1[x][i].count(*it);
- b = t1[y][i].count(*it);
- cmp = a - b;
- if(cmp < 0) return false;
- else if(cmp > 0) return true;
- }
- a = t1[x][i].size();
- b = t1[y][i].size();
- cmp = a - b;
- if(cmp < 0) return false;
- else if(cmp > 0) return true;
- }
- return true;
- }
- };
- int cmp(multiset<int> x[], multiset<int> y[]) {
- int a, b, cmp;
- if(!graph) {
- for(int i = 0; i <= maximumDepth; i++) {
- for(auto it = x[i].begin(); it != x[i].end(); it++) {
- a = x[i].count(*it);
- b = y[i].count(*it);
- cmp = a - b;
- if(cmp < 0) return -1;
- else if(cmp > 0) return 1;
- }
- a = x[i].size();
- b = y[i].size();
- cmp = a - b;
- if(cmp < 0) return -1;
- else if(cmp > 0) return 1;
- }
- return 0;
- }
- else {
- for(int i = 0; i <= maximumDepth; i++) {
- for(auto it = x[i].begin(); it != x[i].end(); it++) {
- a = x[i].count(*it);
- b = y[i].count(*it);
- cmp = a - b;
- if(cmp < 0) return -1;
- else if(cmp > 0) return 1;
- }
- a = x[i].size();
- b = y[i].size();
- cmp = a - b;
- if(cmp < 0) return -1;
- else if(cmp > 0) return 1;
- }
- return 0;
- }
- }
- void travellingPartition(int s1, int e1, int s2, int e2) {
- clearTravellingTable(s1, e1, s2, e2);
- buildTravellingTable(s1, e1, s2, e2);
- for(int i = s1; i <= e1; i++)
- z[i] = i;
- graph = false;
- sort(z+s1, z+e1+1, comp);
- int mid = (s1+e1)/2;
- int a, b;
- for(int i = s1+1; i <= mid; i+= 2) {
- a = M[z[i]], b = M[z[i-s1+mid]];
- swap(M[z[i]], M[z[i-s1+mid]]);
- swap(invM[a], invM[b]);
- }
- // graph = true;
- // sort(z+s2, z+e2+1, comp);
- // int mid = (s2+e2)/2;
- // for(int i = s2+1; i <= mid; i+= 2) {
- // a = M[i], b = M[i-s2+mid];
- // swap(M[i], M[i-s2+mid]);
- // swap(invM[a], invM[b]);
- // }
- }
- bool sharedEdgesTravelEquivalent(int s1, int e1, int s2, int e2) {
- u1.clear();
- u2.clear();
- int node, to;
- int mid1 = (s1+e1)/2;
- for(int i = s1; i <= mid1; i++) {
- node = M[i];
- for(int j = 0; j < g1[node].size(); j++) {
- to = g1[node][j];
- if(to > mid1) {
- u1.push_back(node);
- u1.push_back(to);
- }
- }
- }
- int mid2 = (s2+e2)/2;
- for(int i = s2; i <= mid2; i++) {
- node = M[i];
- for(int j = 0; j < g2[node].size(); j++) {
- to = g2[node][j];
- if(to > mid2) {
- u2.push_back(node);
- u2.push_back(to);
- }
- }
- }
- sort(u1.begin(), u1.end());
- sort(u2.begin(), u2.end());
- for(int i = 0; i < u1.size(); i++)
- matched[i] = 0;
- bool ok = true;
- bool foundMatch;
- for(int i = 0; i < u1.size(); i++) {
- foundMatch = false;
- for(int j = 0; j < u1.size(); j++) { // j can be the same i!!! Necessary for a correct algorithm
- if(matched[j]) continue;
- if(cmp(t1[i], t1[j]) == 0) {
- matched[j] = true;
- foundMatch = true;
- break;
- }
- }
- if(!foundMatch) {
- ok = false;
- break;
- }
- }
- if(!ok) return false;
- else return true;
- for(int i = 0; i < u2.size(); i++)
- matched[i] = 0;
- for(int i = 0; i < u2.size(); i++) {
- foundMatch = false;
- for(int j = 0; j < u2.size(); j++) { // j can be the same i!!! Necessary for a correct algorithm
- if(matched[j]) continue;
- if(cmp(t2[i], t2[j]) == 0) {
- matched[j] = true;
- foundMatch = true;
- break;
- }
- }
- if(!foundMatch) {
- ok = false;
- break;
- }
- }
- if(!ok) return false;
- else return true;
- }
- bool areIso(int s1, int e1, int s2, int e2) {
- if (s1 == e1 && s2 == e2) {
- if(g1[M[s1]].size() == g2[s2].size()) {
- swap(M[s1], M[invM[s2]]);
- return true;
- }
- return false;
- }
- else if (s1 + 1 == e1 && s2 + 1 == e2) {
- if(g1[M[s1]].size() == g2[s2].size() && g1[M[e1]].size() == g2[e2].size()) {
- swap(M[s1], M[invM[s2]]), swap(M[e1], M[invM[e2]]);
- return true;
- }
- else if(g1[M[s1]].size() == g2[e2].size() && g1[M[e1]].size() == g2[s2].size()) {
- swap(M[s1], M[invM[e2]]), swap(M[e1], M[invM[s2]]);
- return true;
- }
- return false;
- }
- int mid1 = (s1+e1)/2;
- int mid2 = (s2+e2)/2;
- if (areIso(s1, mid1, s2, mid2) && areIso(mid1+1, e1, mid2+1, e2)) {
- travellingPartition(s1, e1, s2, e2);
- if (sharedEdgesTravelEquivalent(s1, e1, s2, e2)) {
- return true;
- }
- }
- else if (areIso(s1, mid1, mid2+1, e2) && areIso(mid1+1, e1, s2, mid2)) {
- travellingPartition(s1, e1, s2, e2);
- if (sharedEdgesTravelEquivalent(s1, e1, s2, e2)) {
- // for(int i = 0; i <= b; i++)
- // m[d][i] = m[d+1][i];
- for(int i = s1+1; i <= mid; i+= 2) {
- a = M[z[i]], b = M[z[i-s1+mid]];
- swap(M[z[i]], M[z[i-s1+mid]]);
- swap(invM[a], invM[b]);
- }
- }
- }
- return false;
- }
- int main() {
- cout << "Enter the number of nodes of the 1st Graph:\n";
- cin >> n1;
- cin.ignore();
- cout << "Enter the edges in pseudo-DIMACS format, terminate by \"e\" in a line\n";
- string s;
- while(true) {
- getline(cin, s);
- if(s == "e") break;
- stringstream ss(s);
- ss >> s;
- int a, b;
- ss >> a >> b;
- a--; b--;
- e1.insert(make_pair(a, b));
- }
- for(auto it = e1.begin(); it != e1.end(); it++) {
- g1[it->first].push_back(it->second);
- g1[it->second].push_back(it->first);
- }
- cout << "Enter the number of nodes of the 2nd Graph:\n";
- cin >> n2;
- cin.ignore();
- cout << "Enter the edges in pseudo-DIMACS format, terminate by \"e\" in a line\n";
- while(true) {
- getline(cin, s);
- if(s == "e") break;
- stringstream ss(s);
- ss >> s;
- int a, b;
- ss >> a >> b;
- a--; b--;
- e2.insert(make_pair(a, b));
- }
- for(auto it = e2.begin(); it != e2.end(); it++) {
- g2[it->first].push_back(it->second);
- g2[it->second].push_back(it->first);
- }
- if(n1 != n2) {
- cout << "KABOOM" << endl;
- cout << "The given Graph are not Isomorphic\n";
- return 0;
- }
- n = n1;
- maximumDepth = n-1;
- for(int i = 0; i < 20; i++)
- for(int j = 0; j < n; j++)
- m[i][j] = j;
- for(int i = 0; i < n; i++) {
- M[i] = i;
- invM[i] = i;
- }
- for(int i = 0; i < n; i++) {
- for(int j = 0; j <= maximumDepth; j++) {
- printSet2(t1[i][j]);
- cout << ' ';
- }
- cout << endl;
- }
- // int ans = areIso(0, 0, 0);
- // if(ans == 1) {
- // cout << "The 2 given Graphs are Isomorphic\n";
- // }
- // else if(ans == -1) {
- // cout << "The 2 given Graphs are not Isomorphic\n";
- // }
- // else { // ans == 0, (function is bugged)
- // cout << "No Answer produced for the 2 given Graphs, check the code for bugs\n";
- // }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement