题目链接:D. Two Graphs
题目大意
两张图G1和G2, 最多只有8个节点, 两个节点之间最多有一条边, 两张图节点个数都为n, 边数为m1和m2
求由多少种方案, 从G2中选出m1条边, 使得G1和G2重构
思路
枚举n个节点的全排列, 就是将G2中节点和G1的节点一一对应起来, 一共由n!中对应方案, 判断每一种方案是否可行, 如果可行, 那将方案用一个unsigned long long保存起来(最多8x8条边, 64位每位对应一条边), 然后放进一个set里去重, 最后set的size就是答案
代码
语言:C++14 代码长度:1073 运行时间: 40 ms 占用内存:864K 运行结果:答案正确
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int maxn = 20;
int n, m1, m2;
int G1[maxn][maxn], G2[maxn][maxn];
int x[maxn];
int main()
{
while(cin >> n >> m1 >> m2)
{
memset(G1, 0, sizeof(G1));
memset(G2, 0, sizeof(G1));
for(int i=1; i<=n; ++i) x[i] = i;
int a, b;
for(int i=0; i<m1; ++i)
{
cin >> a >> b;
G1[a][b] = 1;
G1[b][a] = 1;
}
for(int i=0; i<m2; ++i)
{
cin >> a >> b;
G2[a][b] = 1;
G2[b][a] = 1;
}
set<ull> S;
do
{
bool flag = 0;
ull t = 0;
for(int i=1; i<=n; ++i)
{
for(int j=i+1; j<=n; ++j)
{
if(G1[i][j]==1 && G2[x[i]][x[j]] == 0)
{
flag = 1;
break;
}
else
{
if(G1[i][j])
{
int xx = x[i];
int yy = x[j];
if(xx>yy) swap(xx, yy);
t |= ((ull)1 << (xx*n+yy));
}
}
}
if(flag) break;
}
if(!flag) S.insert(t);//, cout << t << "**" << endl;
}while(next_permutation(x+1, x+1+n));
cout << S.size() << endl;
}
return 0;
}