题目大意:给你两个图 G1 G2,让你在G2中找有多少个子图与G1 同构

题目分析
首先这个题目的数据量非常小 n=8 ,所以我们可以采取非常暴力的做法,由于G2中如果有点与G1同构的话,我们发现只要改变G2中 点的序号,此时的新图中如果有一部分与G1完全相同,那么这些点构成的图就会与G1同构。这样我们可以对G2中的点进行全排列,判断G1中存在的边的位置,新的G2中是否也存在同样的边即可
然而,直接找next_permutation 会存在重复,比如说,G1中需要的点的位置都没有变,剩下的点位置发生变化,这样也是一组新的排列,这样会导致我们重复计算,我们用一个map来处理这个情况,我们将g2中的边每个边给不同的序号,如果我们找到了一组点的排列,将这一组的信息储存到b变量中,这样再通过map查询是否存在就可以删去重复了

代码:

#include <bits/stdc++.h>
#define cl(a) memset(a,0,sizeof(a))
using namespace std;
int n,m1,m2;
int g[20][20];
int t[20][20];
int a[20];
map<int,int>mp;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    while(cin>>n>>m1>>m2)
    {
        cl(g);
        cl(t);
        mp.clear();
        for(int i=1;i<=m1;i++)
        {
            int x,y;
            cin>>x>>y;
            g[x][y]=1;
            g[y][x]=1;

        }
        for(int i=1;i<=m2;i++)
        {
            int x,y;
            cin>>x>>y;
            t[x][y]=t[y][x]=i;
        }
        int cnt=0;
        for(int i=1;i<=n;i++) a[i]=i;
        do
        {
            int flag=1;
            int b=0;
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    if(g[i][j])
                    {
                        if(t[a[i]][a[j]]==0)flag=0;
                        else b|=1<<t[a[i]][a[j]];
                    }
                }
            }
            if(flag&&mp[b]==0)
            {
                mp[b]=1;
                cnt++;
            }

        }while(next_permutation(a+1,a+1+n));
        cout<<cnt<<endl;
    }
    return 0;
}