链接:D-Two Graphs
题意:给出图G1和G2,求G2的子图中和G1同构的个数。
题解:只有8个点,暴力枚举G2的点每个排列,让G1映射到G2中,求出同构个数a。同构的G2就是在G1有边的对应位置也有边。在求一G1到G1的全排列映射的同构个数b。答案就是a/b。因为每一个和G1同构的子图都会重复计算b次。
#include <bits/stdc++.h> using namespace std; const double EPS = 1e-6; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; const int maxn = 8 + 10; int n, m1, m2; int g1[maxn][maxn], g2[maxn][maxn]; int a[maxn], b[maxn]; int Cal(int g1[][maxn], int g2[][maxn]) { for(int i = 0; i < n; i++) a[i] = i + 1; int ans = 0; do{ for(int i = 0; i < n; i++) b[a[i]] = i + 1; bool ok = true; for(int i = 1; i <= n; i++){ for(int j = 1; j <= n; j++){ if(g1[i][j] == 1 && g2[b[i]][b[j]] != 1){ ok = false; break; } } } if(ok) ans++; }while(next_permutation(a, a + n)); return ans; } int main() { while(scanf("%d%d%d", &n, &m1, &m2) != EOF){ memset(g1, 0, sizeof(g1)); for(int i = 0, a, b; i < m1; i++){ scanf("%d%d", &a, &b); g1[a][b] = 1; g1[b][a] = 1; } memset(g2, 0, sizeof(g2)); for(int i = 0, a, b; i < m2; i++){ scanf("%d%d", &a, &b); g2[a][b] = 1; g2[b][a] = 1; } printf("%d\n", Cal(g1, g2) / Cal(g1, g1)); } return 0; }