POJ3189 Steady Cow Assignment 二分图匹配+二分+思维

这道题知道用二分图匹配+二分,但是真的不好想。。到现在我还是云里雾里的。。

先附上大佬博客Orz:https://www.cnblogs.com/zhengguiping--9876/p/5675712.html

一开始题目就没太懂,看了解释发现,,没思路啊55555...看了大佬博客发现,可以二分枚举区间长度啊。。然后对应dfs里的条件要换。。

附上AC代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

const int MAXN=1005;
const int MAXM=25;
int un,vn;
int g[MAXN][MAXM];
int link[MAXN][MAXM];
bool vis[MAXM];
int num[MAXM],cnt[MAXM];

bool dfs(int u,int l,int r)
{
    for(int v=1;v<=vn;v++)
        if(!vis[v]&&g[u][v]<=r&&g[u][v]>=l)//注意条件
        {
            vis[v]=true;
            if(cnt[v]<num[v])
            {
                link[v][cnt[v]++]=u;
                return true;
            }
            for(int i=0;i<cnt[v];i++)//注意此处仍从0开始
                if(dfs(link[v][i],l,r))
                {
                    link[v][i]=u;
                    return true;
                }
        }
    return false;
}
int hungary(int l,int r)
{
    memset(link,0,sizeof(link));
    memset(cnt,0,sizeof(cnt));
    for(int u=1;u<=un;u++)
    {
        memset(vis,false,sizeof(vis));
        if(!dfs(u,l,r))
            return false;
    }
    return true;
}

int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)==2)
    {
        memset(g,0,sizeof(g));
        int x;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                scanf("%d",&x);
                g[i][x]=j;
            }
        for(int i=1;i<=m;i++)
            scanf("%d",&num[i]);
        un=n,vn=m;
        int l=0,r=m;//二分的是区间长度
        while(l<r)
        {
            int i,mid=(l+r)/2;
            for(i=1;i<=m;i++)
            {
                if(hungary(i,mid+i))//枚举区间大小为mid+1的值,满足条件时则取其最小值
                    break;
            }
            if(i<=m)
                r=mid;
            else
                l=mid+1;
        }
        printf("%d\n",l+1);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Cc_Sonia/article/details/82012173
今日推荐