Two Graphs 牛客第一场D

Two Graphs

题意:给定两棵树G1,G2.问G2中有多少个子图,和G1同构

思路: 同构的意思是边的连接情况相同但和顶点编号无关.n=8

全排列求出所有哈希情况.最后看有多少种合法.  记得去重,给每一条边rand一个权值.

#include<bits/stdc++.h>
#define PI acos(-1.0)
#define pb push_back
#define F first
#define S second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=200;
const int MOD=1e9+7;
template <class T>
bool sf(T &ret){ //Faster Input

    char c; int sgn; T bit=0.1;
    if(c=getchar(),c==EOF) return 0;
    while(c!='-'&&c!='.'&&(c<'0'||c>'9')) c=getchar();
    sgn=(c=='-')?-1:1;
    ret=(c=='-')?0:(c-'0');
    while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
    if(c==' '||c=='\n'){ ret*=sgn; return 1; }
    while(c=getchar(),c>='0'&&c<='9') ret+=(c-'0')*bit,bit/=10;
    ret*=sgn;
    return 1;
}

int t[20],n,m1,m2;
int a[50][50];
int b[50][50];
ull ans;
set<ull> st;
map<int,int> mp[50];

bool check(){
    ans=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(!a[i][j])    continue;
            if(!b[t[i]][t[j]])  return false;
            ans+=mp[t[i]][t[j]];
        }
    }
    return true;
}

int main(void){
    srand(time(0));
    while((scanf("%d%d%d",&n,&m1,&m2))==3){
        memset(a,0,sizeof a);
        memset(b,0,sizeof b);
        for(int i=1;i<=10;i++)  mp[i].clear();
        st.clear();
        for(int i=1;i<=m1;i++){
            int u,v;
            sf(u);sf(v);
            a[u][v]=a[v][u]=1;
        }
        for(int i=1;i<=m2;i++){
            int u,v;
            sf(u);sf(v);
            b[u][v]=b[v][u]=1;
            ll x=rand()%MOD;
            mp[u][v]=x;
            mp[v][u]=x;
        }
        for(int i=1;i<=n;i++)  t[i]=i;
        do{
//            for(int i=1;i<=n;i++)   cout << t[i]<<" ";
//            cout <<"*********"<<endl;
            if(check()) st.insert(ans);
        }while((next_permutation(t+1,t+1+n)));
        printf("%d\n",(int)st.size());
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/haipai1998/article/details/81130237