HDU 5727 Necklace (二分图匹配)

【题意】:求阳珠子最少的褪色的数量。

【解法】:假设现在是先把阴珠子排列了,排列后得到了n个槽位,编号1-n。现在就是要把n个阳珠子放到这个n个槽位里,使得阳珠子褪色最少。同样,我们再枚举阳珠子,如果阳珠子插到i槽位不会褪色,则在这个槽位和该阳珠子之间建一条边。最终,对于这个排列,我们得到了一个关于槽位和阳珠子的二分图(如果你还不知道二分图是什么,请看我上篇转载的博客)。要使褪色最少,即尽量使新建的二分图中的阳珠子放下去。所以求一下二分图的最大匹配res,res即为放下去的数量,n-res即为不得不褪色的阳珠子数量。

然后枚举所有阴珠子的排列(环排列,固定一个位置,其它用next_permutation)。求得所有的n-res,保留最小的那个即为阳珠子最少的褪色的数量

【!!!】

也是看到了HDU上竟然有将近700个人过了这题才来写的,又是一个没学过的知识点:二分图匹配,甚至我连什么是二分图都不知道。于是花了几个小时先搞明白了什么是二分图,什么是匹配,最后囫囵吞枣的把二分图匹配的匈牙利算法看了一遍,现在不敢深究其原理,只求会用基本的。学到现在才明白,ACM最重要的是什么?是积累!遇到不懂的不是留到日后,而是现在立刻就去百度,去查,去学!否则难有建树!

【代码】

/* ***********************************************
Author        :angon
************************************************ */
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define REP(i,k,n) for(int i=k;i'9'; ch=getchar());
    for(; ch>='0'&&ch<='9'; ch=getchar())s=s*10+ch-'0';
    return s;
}
inline void print(int x)
{
    if(!x)return;
    print(x/10);
    putchar(x%10+'0');
}
*/

int pos[N],m,n,mp[N][N],ans;
int head[N],tot;
struct node
{
    int to,next;
}edge[N*N];
void addedge(int u,int v)
{
    edge[tot].to=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}
void init()
{
    mst(head,-1);tot=0;
}
int vis[N],link[N];
bool dfs(int u)
{
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].to;
        if(!vis[v])
        {
            vis[v]=1;
            if(link[v] == -1 || dfs(link[v]))
            {
                link[v]=u;
                return 1;
            }
        }
    }
    return 0;
}

int hungry()
{
    int res=0;
    mst(link,-1);
    for(int i=1;i<=n;i++)
    {
        mst(vis,0);
        if(dfs(i)) res++;
    }
    return n-res;
}

int main()
{
    //freopen("1005.in","r",stdin);
    //freopen("out.txt","w",stdout);
    while(~scann(n,m))
    {
        mst(mp,0);
        REP(i,0,m)
        {
            int x,y;
            scann(x,y); mp[x][y]=1;
        }
        if(n==0 || m==0)
        {
            puts("0");
            continue;
        }
        REPP(i,1,n) pos[i]=i;
        ans = 1112;
        do
        {
            init();
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    int nx=i,pre=i-1;
                    if(pre==0) pre=n;
                    if(!mp[j][pos[nx]] && !mp[j][pos[pre]])
                    {
                        addedge(i,j);
                    }
                }
            }
            ans = min(ans ,hungry());
        }while(next_permutation(pos+1,pos+n));
        printf("%d\n",ans);
    }


    return 0;
}


你可能感兴趣的:(HDU 5727 Necklace (二分图匹配))