牛客网暑期ACM多校训练营(第一场)D Two Graphs (求一个图有多少个子图是另一个图的同构图)

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

时间限制: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.

题意很简单单,但是题目用各种专业的术语表达有点把人绕迷了。题意就是给定两个图 G1和G2 两个图的点个数V是相同的,问你G2的子图中有多少个与G1同构。

思路:因为题目的范围比较小,最多只有8个点,所以我们可以枚举所有的全排列,然后把G2中的点对应的替换一下,然后看看再G1中是否存在这条边如果,存在就用一个用一个变量++,如果最后存在的边数是与G1中边数相等,那么就是符合的。我们要把这个子图哈希成一个具体的值,因为同构图会有重复的,所以我们这里要哈希边,把边的序列哈希成一个值。

代码如下:

#include<bits/stdc++.h>

using namespace std;
const int MAX = 11;
int G[MAX][MAX];
class Edge{
public:
    int u,v;
    Edge();
    Edge(int _u,int _v);
};
Edge edg[MAX*MAX];
typedef unsigned long long ull;
const ull B = 100000007;
int N,E1,E2;
int vec[MAX];
void init(){
    memset(G,0,sizeof(G));
    for(int i=1;i<=N;++i){
        vec[i] = i;
    }
}
int main(void){
    while(cin >> N >> E1 >> E2){
        init();
        int u,v;
        for(int i=1;i<=E1;++i){
            cin >> u >> v;
            G[u][v] = G[v][u] = 1;
        }
        for(int i=1;i<=E2;++i){
            cin >> u >> v;
            edg[i] = Edge(u,v);
        }
        set<ull> st;
        do{
            int cnt = 0;
            ull temp = 0;
            for(int i=1;i<=E2;++i){
                int u = vec[edg[i].u],v = vec[edg[i].v];
                //更换对应的点
                if(G[u][v]){
                    cnt++;
                    //注意这里哈希的是边。每次选的边是一样的,就不会出现重复的
                    temp = temp*B + i;
                }
            }
            if(cnt == E1){
                st.insert(temp);
            }
        }while(next_permutation(vec+1,vec+1+N));
        cout << (int)st.size() << endl;
    }

    return 0;
}
Edge::Edge(){
    u = v = 0;
}
Edge::Edge(int _u,int _v){
    u = _u;
    v = _v;
}

猜你喜欢

转载自blog.csdn.net/zhao5502169/article/details/81129378
今日推荐