Hdu3118 Arbiter【二进制枚举建二分图】

Arbiter

题意

给定 n n n 个点和 m m m 条边,要求删除最少数量的边,使图中没有奇环

n ≤ 15 , m ≤ 300 n \leq 15,m \leq 300 n15,m300

思路

没有奇环的图是二分图

我们可以直接从定义入手,用二进制枚举二分图的两个颜色的点,删除两个集合各自内部的所有边即可,答案取 m i n min min

时间复杂度: O ( m ⋅ 2 n ) O(m \cdot 2 ^ n) O(m2n)

#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;
}
  • 15
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值