Arbiter
题意
给定 n n n 个点和 m m m 条边,要求删除最少数量的边,使图中没有奇环
n ≤ 15 , m ≤ 300 n \leq 15,m \leq 300 n≤15,m≤300
思路
没有奇环的图是二分图
我们可以直接从定义入手,用二进制枚举二分图的两个颜色的点,删除两个集合各自内部的所有边即可,答案取 m i n min min
时间复杂度: O ( m ⋅ 2 n ) O(m \cdot 2 ^ n) O(m⋅2n)
#include<bits/stdc++.h>
#define fore(i,l,r) for(int i=(int)(l);i<(int)(r);++i)
#define fi first
#define se second
#define endl '\n'
#define ull unsigned long long
#define ALL(v) v.begin(), v.end()
#define Debug(x, ed) std::cerr << #x << " = " << x << ed;
const int INF=0x3f3f3f3f;
const long long INFLL=1e18;
typedef long long ll;
std::vector<std::vector<int>> g;
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
int t;
std::cin >> t;
while(t--){
int n, m;
std::cin >> n >> m;
g.assign(n + 1, std::vector<int>());
std::vector<std::pair<int, int>> edge(m);
fore(i, 0, m){
int u, v;
std::cin >> u >> v;
edge[i] = {u, v};
g[u].push_back(v);
g[v].push_back(u);
}
int ans = m;
fore(S, 1, 1 << n){
std::vector<int> sta(n);
fore(j, 0, n) sta[j] = (S >> j & 1);
int n1 = 0, n0 = 0;
fore(i, 0, n){
n1 += sta[i];
n0 += (sta[i] == 0);
}
if(!n1 || !n0) continue;
int cnt = 0;
for(auto [u, v] : edge) cnt += (sta[u] == sta[v]);
ans = std::min(ans, cnt);
}
std::cout << ans << endl;
}
return 0;
}