分析:每个连通块都是独立的,对一个连通块进行分析.如果边数>点数,显然是不可能的,因为每条边要分配给一个点,至少有一个点分配了两次以上.如果边数=点数,就形成了环,有两种方案,顺时针一个环,逆时针一个环.如果边数=点数-1,形成了链,将n个点分配n-1条边,答案为C(n,n-1),也就是n,统计一下每个连通块有多少个点,多少条边就可以了.
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn = 200010, mod = 1e9 + 7; int n, m, cnt1, cnt2, head[maxn], to[maxn], nextt[maxn], tot = 1; bool vis[maxn], vis2[maxn]; long long ans = 0; void add(int x, int y) { to[tot] = y; nextt[tot] = head[x]; head[x] = tot++; } void dfs(int u) { vis[u] = 1; cnt1++; for (int i = head[u]; i; i = nextt[i]) { int t = i, t2; if (t % 2 == 0) t2 = i - 1; else t2 = i + 1; if (!vis2[i]) { cnt2++; vis2[t] = vis2[t2] = 1; } int v = to[i]; if (!vis[v]) dfs(v); } } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) { int u, v; scanf("%d%d", &u, &v); add(u, v); add(v, u); } for (int i = 1; i <= n; i++) { if (!vis[i]) { cnt1 = 0; cnt2 = 0; dfs(i); if (cnt1 == cnt2) { if (ans == 0) ans = 2; else ans = (ans * 2) % mod; } if (cnt1 == cnt2 + 1) { if (ans == 0) ans = cnt1; else ans = (ans * cnt1) % mod; } } } printf("%lld ", ans); return 0; }