hdu 3118 Arbiter

http://acm.hdu.edu.cn/showproblem.php?pid=3118

 
题意:删除最少的边使图没有奇环
 
二分图的定义:如果顶点能分为两个互不相交的子集,则图为二分图
二分图的判定:如果二分图能黑白染色成功,则图为二分图
而黑白染色,其实就是判断环是奇环还是偶环
如果是奇环,一定会有黑黑或白白相撞
所以删除最小的边使图没有奇环,就是使图能够黑白染色
也就是删除最少的边,使图变成一个二分图
 
n只有15
完全可以枚举左边有哪些点,右边有哪些点
因为二分图的两个点集互不相交
所以两个点集内部的边数
就是使当前点的分布状态能形成二分图需要删去的边数
 
所有枚举的状态取最小
 
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int e[16][16];
int a[16],b[16];
int n;
int solve(int S)
{
    a[0]=b[0]=0;
    for(int i=0;i<n;i++)
        if(S&(1<<i)) a[++a[0]]=i+1;
        else b[++b[0]]=i+1;
    int r=0;
    for(int i=1;i<=a[0];i++)
        for(int j=i+1;j<=a[0];j++)
        {
            if(i==j) continue;
            r+=e[a[i]][a[j]];
        } 
    for(int i=1;i<=b[0];i++)
        for(int j=i+1;j<=b[0];j++)
        {
            if(i==j) continue;
            r+=e[b[i]][b[j]];
        }
    return r;
}
int main()
{
    int S,T,m,u,v,ans;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        memset(e,false,sizeof(e));
        ans=m+1;
        while(m--)
        {
            scanf("%d%d",&u,&v);
            u++; v++;
            e[u][v]++; e[v][u]++;
        }
        S=1<<n;
        for(int i=0;i<S;i++)  ans=min(ans,solve(i));
        printf("%d
",ans);
    }
}
 
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7436395.html