牛客网暑期ACM多校训练营(第一场):D-Two Graphs

链接: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;
}

猜你喜欢

转载自www.cnblogs.com/chenquanwei/p/9341759.html
今日推荐