题意:
n个点,m1条边的图E1,n个点,m2条边的图E2。求图E2有多少子图跟图E1同构。
题解:
用STL的全排列函数next_permutation()枚举映射。对于每一种映射枚举每一条边判断合法性。
总情况数要除以图E1的自同构数去重。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; int n, m1, m2; int u, v, d; int ans; int p[10]; int a[9][9], b[9][9]; int main() { while(~scanf("%d%d%d", &n, &m1, &m2)) { d = ans = 0; memset(a, 0, sizeof(a)); memset(b, 0, sizeof(b)); for(int i = 1; i <= m1; i++) { scanf("%d%d", &u, &v); a[u][v] = a[v][u] = 1; } for(int i = 1; i <= m2; i++) { scanf("%d%d", &u, &v); b[u][v] = b[v][u] = 1; } for(int i = 1; i <= 8; i++) p[i] = i; // 图E1的自同构 do { int f = 1; for(int i = 1; f && i <= n; i++) for(int j = 1; f && j <= n; j++) if(a[i][j] && (!a[p[i]][p[j]])) f = 0; if(f) d++; } while(next_permutation(p+1, p+n+1)); // 图E2和E1的同构 do { int f = 1; for(int i = 1; f && i <= n; i++) for(int j = 1; f && j <= n; j++) if(a[i][j] && (!b[p[i]][p[j]])) f = 0; if(f) ans++; } while(next_permutation(p+1, p+n+1)); printf("%d ", ans/d); } }