#include using namespace std; const int N = 20, M = N << 1; #define int long long // 链式前向星 int e[M], h[N], idx, w[M], ne[M]; void add(int a, int b) { e[idx] = b, ne[idx] = h[a], h[a] = idx++; } int g[N][N]; int f[N][N]; int st[N]; int flag[N]; int n, m; // https://blog.csdn.net/Emm_Titan/article/details/123597082 void dfs(int u) { st[u] = 1; for (int i = 1; i <= n; i++) f[u][i] = flag[i] ^ 1; for (int i = h[u]; ~i; i = ne[i]) { int v = e[i]; if (st[v]) continue; dfs(v); for (int i = 1; i <= n; i++) { if (flag[i]) continue; int sum = 0; for (int j = 1; j <= n; j++) if (g[i][j] and !flag[j]) sum += f[v][j]; f[u][i] *= sum; } } } signed main() { memset(h, -1, sizeof h); cin >> n >> m; int a, b; for (int i = 1; i <= m; i++) { cin >> a >> b; g[a][b] = g[b][a] = 1; } for (int i = 1; i < n; i++) { cin >> a >> b; add(a, b), add(a, b); } int ans = 0; for (int s = 0; s < (1 << n); s++) { for (int i = 0; i < n; i++) flag[i + 1] = s >> i & 1; // 多次调用dfs memset(st, 0, sizeof st); dfs(1); int sum = 0; for (int i = 1; i <= n; i++) sum += f[1][i]; if (__builtin_popcount(s) & 1) // 似乎是查询s里有多少个数字1 ans -= sum; else ans += sum; } printf("%lld\n", ans); }