【HDU】5727 Necklace

18 篇文章 0 订阅
5 篇文章 0 订阅

Necklace


题目链接


题目大意

    现在有n颗阳珠子,n颗阴珠子,我们需要用这2n颗珠子排成一个项链,要求阴阳相间。除此以外,某些珠子在一起还会互相影响,现在要求某种排列,使得受到影响的阳珠子数目最少。


题解

二分图最大匹配

    因为是一个环,所以我们只用考虑 (n1)! 种排列就行了,我们首先枚举阴珠子的排列,然后对于某个位置,如果该位置可以放阳珠子,就建一条边,最后用n减去最大匹配数就是受影响的阳珠子的数目。

  • 注意n=0的情况要输出0…

代码

#include <iostream>
#include <cstring>
#include <cstdio>
#define INF 0x7fffffff

using namespace std;

int n,m,mp[15][15],g[15][15],sta[15],h;
int link[15],ans;
bool flag[15],vis[15];

bool Dfs(int u)
{
    for (int i=1;i<=n;i++) if (!vis[i] && g[u][i])
    {
        vis[i]=1;
        if (!link[i] || Dfs(link[i]))
        {
            link[i]=u;
            return 1;
        }
    }
    return 0;
}

int deal(int n)
{
    memset(g,0,sizeof(g));
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++) if (!mp[j][sta[i]] && !mp[j][sta[i-1]]) g[i][j]=1;
    int ans=0;
    memset(link,0,sizeof(link));
    for (int i=1;i<=n;i++)
    {
        memset(vis,0,sizeof(vis));
        if (Dfs(i)) ans++;
    }
    return ans;
}

void dfs(int depth)
{
    if (depth==n)
    {
        sta[0]=sta[n];
        ans=min(n-deal(n),ans);
        sta[0]=0;
        return ;
    }
    for (int i=2;i<=n;i++) if (!flag[i])
    {
        //if (depth==n-1 && sta[1]>i) return ;
        flag[i]=1;
        sta[h++]=i;
        dfs(depth+1);
        sta[--h]=0;
        flag[i]=0;
    }
}

int main()
{
    while (scanf("%d%d",&n,&m)!=EOF)
    {
        if (n==0)
        {
            printf("0\n");
            continue;
        }
        memset(sta,0,sizeof(sta));
        memset(flag,0,sizeof(flag));
        memset(mp,0,sizeof(mp));

        int a,b;
        for (int i=0;i<m;i++)
        {
            scanf("%d%d",&a,&b);
            mp[a][b]=1;
        }
        h=1;
        sta[h++]=1; flag[1]=1;
        ans=INF;
        dfs(1);
        printf("%d\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值