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

有G1,G2两个图G1边数较少

求G2中有几个子图与G1完全相同(点的编号只是相对的)

找出所有的对应关系,看G1是否完全被G2覆盖,并找出覆盖G1的那些边

因为点是相同的,所以如果边也是相同的,就说明这两个图是完全相同的

可以依据这点来去重

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <map>
using namespace std;
map<int,int>mp;
int n,m1,m2,x,y;
int mp1[10][10], mp2[10][10], a[10];
int main()
{
    for(int i=1;i<=8;i++) a[i] = i; // 初始化
    while(scanf("%d%d%d",&n,&m1,&m2)!=EOF){
        memset(mp1, 0, sizeof mp1); // 存边
        memset(mp2, 0, sizeof mp2); // 记录边的编号以及是否有这条边
        mp.clear();
        for(int i=1;i<=m1;i++){
            scanf("%d%d",&x,&y);
            mp1[x][y] = mp1[y][x] = 1;
        }
        for(int i=1;i<=m2;i++){
            scanf("%d%d",&x,&y);
            mp2[x][y] = mp2[y][x] = i; // 第i条边编号为i
        }
        int ans = 0;
        do{
            // G1 i -> G2 a[i]  映射关系
            int flag = 1, b = 0;
            // 判断是否满足映射关系
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    if(mp1[i][j]){ // 当小图中有边则大图中必须有对应的边
                        if(mp2[a[i]][a[j]] == 0) flag = 0;
                        else b |= 1<<mp2[a[i]][a[j]];
                    }
                }
            }
            if(flag && mp[b] == 0){ // 如果满足并且这种状态没有出现过就答案+1
                ans ++;
                mp[b] = 1;
            }
        }while(next_permutation(a+1, a+1+n)); // 全排列来得到所有可能的映射关系
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/w326159487/article/details/81130502
今日推荐