#include <bits/stdc++.h> using namespace std; usi...

Created on: November 5, 2026

Answered using GPT-6 by Chat01

Question

#include <bits/stdc++.h>

using namespace std;
using ld = long double;

const int MOD = 1e9 + 7;
const int oo = 2e9;
const long long OO = 4e18;
const int N = 1e5 + 5;

//vector<pair<int, int> > g[N];
//vector<pair<int, int> > e;
//
//void add_edge(int u, int v) {
// g[u].push_back((int)e.size()); e.push_back({u, v});
// g[v].push_back((int)e.size()); e.push_back({u, v});
//}

void solve() {
// int n;
// cin >> n;
int n, m;
cin >> n >> m;
vector<vector<int> > g(n);
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
u--; v--;
g[u].push_back(v);
g[v].push_back(u);
}
vector<vector<int> > dp((1 << n), vector<int>(n));
dp[1][0] = 1;
for (int msk = 0; msk < (1 << n); msk++) {
for (int fr = 0; fr < n; fr++) {
if ((msk >> fr) & 1) {
for (int to : g[fr]) {
if (!((msk >> to) & 1)) {
dp[msk | (1 << to)][to] += dp[msk][fr];
}
}
}
}
}
int ans = 0;
for (int v : g[0]) {
ans += dp[(1 << n) - 1][v];
}
cout << ans;
}

int32_t main() {
ios_base::sync_with_stdio(0); cin.tie(0);
int tests = 1;
// cin >> tests;
while (tests--) {
solve();
}
return 0;
}

#include <iostream>
#include <vector>
using namespace std;

vector < vector < int > > a;
vector < int > x1;
vector < bool > p;
int n, m, k = 0;

void DFS(int x){
p[x] = true; m++;
if (m == n && x1[x] == 1)
k++;
for (int i = 0; i < a[x].size(); i++)
if (!p[a[x][i]])
DFS(a[x][i]);
p[x] = false; m--;
}

int main()
{
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> n >> m;
a.resize(n + 1);
for (int i = 0; i < m; i++){
int x, y;
cin >> x >> y;
a[x].push_back(y);
a[y].push_back(x);
}
p.resize(n + 1);
m = 0;
x1.resize(n + 1);
for (int i = 0; i < a[1].size(); i++)
x1[a[1][i]] = 1;
DFS(1);
cout << k;
return 0;
}
/**
9 17
1 2
1 3
1 5
1 6
2 3
2 4
2 5
2 9
3 4
3 6
3 7
3 8
4 8
4 9
5 9
6 7
7 8
*/
12 77
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
1 10
1 11
1 12
2 3
2 4
2 5
2 6
2 7
2 8
2 9
2 10
2 11
2 12
3 4
3 5
3 6
3 7
3 8
3 9
3 10
3 11
3 12
4 5
4 6
4 7
4 8
4 9
4 10
4 11
4 12
5 6
5 7
5 8
5 9
5 10
5 11
5 12
6 7
6 8
6 9
6 10
6 11
6 12
7 8
7 9
7 10
7 11
7 12
8 9
8 10
8 11
8 12
9 10
9 11
9 12
10 11
10 12
11 12
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
1 10
1 11
1 12
поч на этом тесте разные ответфы

Answer

Text version

Потому что в первом коде происходит переполнение int.

Вот проблемные места:

cpp
dp[msk | (1 << to)][to] += dp[msk][fr];

и

cpp
ans += dp[(1 << n) - 1][v];

В твоём тесте первые 66 рёбер образуют полный граф на 12 вершинах K12K_{12}. Остальные 11 рёбер — повторные рёбра из вершины 1.

В полном графе на 12 вершинах количество гамильтоновых циклов с фиксированной стартовой вершиной, с учётом направления:

(12−1)!=11!=39 916 800(12-1)! = 11! = 39\,916\,800

Но у тебя 11 рёбер из вершины 1 продублированы. Оба алгоритма учитывают эти повторения, поэтому количество подсчитанных обходов:

11!⋅2⋅2=159 667 20011!\cdot 2\cdot 2 = 159\,667\,200

Это число помещается в int, но промежуточные значения тоже нужно проверять.

В данном конкретном тесте максимальные значения DP не должны превышать итоговый ответ, поэтому переполнения int здесь нет.

Настоящая причина различия — во втором DFS:

cpp
if (m == n && x1[x] == 1) k++;

x1[x] хранит только факт существования ребра между 1 и x, а первый алгоритм:

cpp
for (int v : g[0]) { ans += dp[(1 << n) - 1][v]; }

учитывает каждое ребро, включая повторные.

Поэтому:

  • Первый алгоритм выдаёт 159667200.
  • Второй алгоритм выдаёт 79833600.

Чтобы исправить второй алгоритм, замени:

cpp
x1[a[1][i]] = 1;

на:

cpp
x1[a[1][i]]++;

И условие:

cpp
if (m == n && x1[x] == 1) k++;

на:

cpp
if (m == n) k += x1[x];

Теперь оба алгоритма будут считать одинаково.

Важно: если по условию граф простой, то повторных рёбер во входных данных вообще не должно быть. Если они допустимы, нужно учитывать их кратность в обоих алгоритмах.

Share this Q&A