2018牛客网暑期ACM多校训练营(第一场) D - Two Graphs - [无向图同构]

题目链接:https://www.nowcoder.com/acm/contest/139/D

题目描述

Two undirected simple graphs   and   where   are isomorphic when there exists a bijection   on V satisfying   if and only if {x, y} ∈ E 2.
Given two graphs   and  , count the number of graphs   satisfying the following condition: 
.
* G 1 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.

输入

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.

题意:

两个简单无向图G1和G2,问G2的子图中有多少个与G1同构。

题解:

显然枚举子图不现实,假设phi(x)是从G1中的某个点映射到G2的某个点的函数,

那么,从最开始 phi[1:n] = (1,2,3,…,n) 开始全排列,可以枚举出G1对应到G2的全部情况,只要判断G2中有没有相应的边即可。

同时,要考虑自同构的情况,通过G1映射到自身判断是否自同构,最后答案除以自同构数即可。

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=10;
const int maxm=maxn*(maxn-1)/2;

int n,m1,m2;
int E1[maxn][maxn],u[maxm],v[maxm];
int E2[maxn][maxn];
int phi[maxn];

int main()
{
    while(scanf("%d%d%d",&n,&m1,&m2)!=EOF)
    {
        memset(E1,0,sizeof(E1));
        memset(E2,0,sizeof(E2));
        for(int i=1;i<=m1;i++) //G1
        {
            scanf("%d%d",&u[i],&v[i]);
            E1[u[i]][v[i]]=E1[v[i]][u[i]]=1;
        }
        for(int i=1,a,b;i<=m2;i++) //G2
        {
            scanf("%d%d",&a,&b);
            E2[a][b]=E2[b][a]=1;
        }

        for(int i=1;i<=n;i++) phi[i]=i; //初始化映射函数
        int ans=0,cnt=0;
        do
        {
            bool ok=1; //标记是否与G2的某个子图同构
            bool self=1; //标记是否自同构
            for(int i=1;i<=m1;i++)
            {
                int a=phi[u[i]],b=phi[v[i]];
                if(E2[a][b]==0) ok=0;
                if(E1[a][b]==0) self=0;
            }
            if(ok) ans++;
            if(self) cnt++;
        }while(next_permutation(phi+1,phi+n+1));

        printf("%d\n",ans/cnt);
    }
}

猜你喜欢

转载自www.cnblogs.com/dilthey/p/9346371.html
今日推荐