hdu5727 Necklace(数组全排列 状态枚举+匈牙利)

Necklace

Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 3662    Accepted Submission(s): 1116


 

Problem Description

SJX has 2*N magic gems. N of them have Yin energy inside while others have Yang energy. SJX wants to make a necklace with these magic gems for his beloved BHB. To avoid making the necklace too Yin or too Yang, he must place these magic gems Yin after Yang and Yang after Yin, which means two adjacent gems must have different kind of energy. But he finds that some gems with Yang energy will become somber adjacent with some of the Yin gems and impact the value of the neckless. After trying multiple times, he finds out M rules of the gems. He wants to have a most valuable neckless which means the somber gems must be as less as possible. So he wonders how many gems with Yang energy will become somber if he make the necklace in the best way.

 

Input

  Multiple test cases.

  For each test case, the first line contains two integers N(0≤N≤9),M(0≤M≤N∗N), descripted as above.

  Then M lines followed, every line contains two integers X,Y, indicates that magic gem X with Yang energy will become somber adjacent with the magic gem Ywith Yin energy.

 

Output

One line per case, an integer indicates that how many gem will become somber at least.

 

Sample Input

 

2 1 1 1 3 4 1 1 1 2 1 3 2 1

 

Sample Output

 

1 1

 

Author

HIT

 

Source

2016 Multi-University Training Contest 1

 

Recommend

wange2014   |   We have carefully selected several similar problems for you:  6447 6446 6445 6444 6443 

题意:

有2n(0<=n<=9)个珠子,分为阴阳两种,每种各n个。

用这2n个珠子做成一个项链,使得相邻两个珠子的极性是不一样的,有一些阳珠子与一些阴性的珠子相邻会削弱

给你m(0<=m<=n*(n-1)/2)个关系[x,y]表示阳性珠子x会被阴性珠子y在相邻情况下所削弱。问你最少有多少个阳性。

题解:

先记录下阴阳会被削弱的矛盾关系;

然后全排列枚举出所有阴性珠子的排列情况  (因为是环,所以有(n-1)!种),然后在它们之间插入阳性的珠子,判断出阳性珠子插入在之间 不会被削弱的合法匹配关系。

我们通过匈牙利算法算出最大匹配sum,然后算出n-sum,对于每种排列取最小值就得到了我们想要的答案,注意特判下n=0的情况。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=10,M=0x3f3f3f3f;
int n,m,ans;
int a[N],y[N];//a与y匹配
bool mp[N][N],vis[N][N],use[N];//矛盾关系 匹配关系 是否尝试过
bool dsf(int x)
{
  for(int i=1; i<=n; i++)
  {
    if(!use[i]&&vis[i][x]) //关系可行 没尝试过
    {
      use[i]=1;//标记试过
      if(!y[i]||dsf(y[i])) //未匹配||尝试换
      {
        y[i]=x;
        return 1;
      }
    }
  }
  return 0;
}
int hungary()//最大匹配
{
  int res=0;
  memset(y,0,sizeof y);//初始化y集合
  for(int i=1; i<=n; i++)
  {
    memset(use,0,sizeof use);//尝试过的x集合
    if(dsf(i))
      res++;//匹配数
  }
  return res;
}
int main()
{
  while(~scanf("%d %d",&n,&m))
  {
    if(!n)
    {
      printf("0\n");
      continue;
    }
    memset(mp,0,sizeof mp);
    while(m--)
    {
      int u,v;
      scanf("%d %d",&u,&v);
      mp[u][v]=1;//记录矛盾关系
    }
    for(int i=1; i<=n; i++)
      a[i]=i;//全排列数组
    ans=M;
    do
    {
      memset(vis,0,sizeof vis);//匹配关系初始化
      for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)//检查这个时候两边是否都可以放
          if(!mp[i][a[j]]&&!mp[i][a[j%n+1]])//环
            vis[i][j]=1;//在该 状态or排列 下可行的匹配关系
      ans=min(ans,n-hungary());//计算最大匹配数
    }
    while(next_permutation(a+2,a+1+n));//因为是个环,所以只需要全排列(n-1)个数就好,少了一个*n的复杂度
    printf("%d\n",ans);
  }
}

猜你喜欢

转载自blog.csdn.net/qq_41668093/article/details/82956431
今日推荐