Newcoder 139 D.Two Graphs(next_permutation)

探讨了图同构的概念及其在子图计数问题中的应用,通过枚举所有点编号的排列来判断图G1是否为图G2的同构子图,并考虑自同构的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

两个无向简单图G1=<V,E1>,G2=<V,E2>G1=<V,E1>,G2=<V,E2>同构表示存在一个VV之间的双射ϕ使得(x,y)E1(x,y)∈E1当且仅当(ϕ(x),ϕ(y))E2(ϕ(x),ϕ(y))∈E2. 现给出两个图G1=<V,E1>,G2=<V,E2>G1=<V,E1>,G2=<V,E2>,统计图G=<V,E>G=<V,E>的数量,使其满足EE2E⊂E2G1G1GG同构

Input

多组用例,每组用例首先输入三个整数n,m1,m2表示点数和两个图的边数,之后m1m1行输入图G1G1m1m1条边,最后m2m2行输入图G2G2m2m2条边

(1n8,1m1m2n(n1)2)(1≤n≤8,1≤m1≤m2≤n(n−1)2)

Output

输出满足条件的图GG的个数

Sample Input

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

Sample Output

2
3

Solution

该种同构本质上是对点的重排,故n!枚举所有点编号的排列,得到G1G1转化编号后的图后判断其是否为G2G2子图即可,但是注意到由于自同构的存在,以上求出的很多方案本质对应的是一个图,故在求出所有满足条件的排列方案数量后,除去自同构数量即为答案

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m1,m2,u[100],v[100],g1[10][10],g2[10][10],a[10];
int main()
{
    while(~scanf("%d%d%d",&n,&m1,&m2))
    {
        memset(g1,0,sizeof(g1));
        for(int i=1;i<=m1;i++)
        {
            scanf("%d%d",&u[i],&v[i]);
            g1[u[i]][v[i]]=g1[v[i]][u[i]]=1;
        }
        memset(g2,0,sizeof(g2));
        for(int i=1;i<=m2;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            g2[x][y]=g2[y][x]=1;
        }
        for(int i=1;i<=n;i++)a[i]=i;
        int ans=0,num=0;
        do
        {
            int flag1=1,flag2=1;
            for(int i=1;i<=m1;i++)
            {
                int x=a[u[i]],y=a[v[i]];
                if(!g1[x][y])flag1=0;
                if(!g2[x][y])flag2=0;
            }
            ans+=flag2;
            num+=flag1;
        }while(next_permutation(a+1,a+n+1));
        printf("%d\n",ans/num);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值