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

链接:https://www.nowcoder.com/acm/contest/139/D
来源:牛客网
 

Two Graphs

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format: %lld

题目描述

Two undirected simple graphs and where are isomorphic when there exists a bijection on V satisfying  if and only if {x, y} ∈ E2.
Given two graphs and , count the number of graphs satisfying the following condition:
* .
* G1 and G are isomorphic.

输入描述:

The input consists of several test cases and is terminated by end-of-file.
The first line of each test case contains three integers n, m1 and m2 where |E1| = m1 and |E2| = m2.
The i-th of the following m1 lines contains 2 integers ai and bi which denote {ai, bi} ∈ E1.
The i-th of the last m2 lines contains 2 integers ai and bi which denote {ai, bi} ∈ E2.

输出描述:

For each test case, print an integer which denotes the result.

示例1

输入

复制

3 1 2
1 3
1 2
2 3
4 2 3
1 2
1 3
4 1
4 2
4 3

输出

复制

2
3

备注:

* 1 ≤ n ≤ 8
* 
* 1 ≤ ai, bi ≤ n
* The number of test cases does not exceed 50.

题意:

给你一个小图,一个大图。

问你在大图中能找到多少个形状和小图一样的   在大图G2中找G1的同构子图 

所以 把所有的G2所有的点存在一个a数组中,进行全排列 再进行点与点的一一映射

然后再与 G1 进行对应配对 看是否可满足同构

代码:

#include <iostream>
#include <string.h>
#include<algorithm>
#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;//存在一条x到y的无向边
    }
    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 
      {
//          for(int i=1;i<=n;i++)
//            printf("%d\t",a[i]);
//                puts("");
        ans ++;
        mp[b] = 1;//标记
      }
    }
    while(next_permutation(a+1, a+1+n));  //全排列来得到所有可能的映射关系
    printf("%d\n",ans);
  }
  return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41668093/article/details/81176431
今日推荐