zju 3209 学习dancing links
poj 1509 最小表示法

poj 3189 二分+多重匹配

scturtle posted @ 2010年11月08日 03:42 in algorithm , 2539 阅读

http://www.cublog.cn/u3/113538/showart_2212681.html

http://hi.baidu.com/scaneelingg/blog/item/a639111e08b98ac2a7866992.html

总是想不到二分.学到了多重匹配,X中一个点可以匹配Y中多个点,但Y中的点只能匹配一个X中的点.做法貌似是匈牙利算法的变种.也可以用最大流来做多重匹配,每一个X中的点连S,容量为1,每一个牛棚连T,容量为牛棚容量,XY之间按二分上下限连,但效率貌似要低.

#include <cstdio>
#include <cstring>

#define maxn 1001
#define maxm 21
int n,m;
//bool map[maxn][maxm];
int map[maxn][maxm];
int match[maxm][maxn];
bool v[maxm];
int cap[maxm];

int c[maxm];
int l,r;

int dfs(int p)
{
    int i,j;
    for(i=1;i<=m;i++)
        //if(map[p][i] && !v[i])
        if(l<=map[p][i] && map[p][i]<=r && !v[i])
        {
            v[i]=1;
            if(cap[i])
            {
                --cap[i];
                match[i][ ++match[i][0] ]=p;
                return 1;
            }
            else
            {
                for(j=1;j<=match[i][0];j++)
                    if(dfs(match[i][j]))
                    {
                        match[i][j]=p;
                        return 1;
                    }
            }
        }
    return 0;
}

int maxmatch()
{
    int i,ans=0;
    for(i=1;i<=m;i++)
        match[i][0]=0;
    for(i=1;i<=n;i++)
    {
        memset(v,false,sizeof(v));
        ans+=dfs(i);
    }
    return ans;
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("in","r",stdin);
    freopen("out","w",stdout);
#endif
    int i,j,N,B,b;scanf("%d%d",&N,&B);
    for(i=1;i<=N;i++)
        for(j=1;j<=B;j++)
        {
            scanf("%d",&b);
            map[i][b]=j;
        }

    for(j=1;j<=B;j++)
        scanf("%d",&c[j]);

    l=r=1;
    int ans=B+1;
    while(l<=r && r<=B)
    {
        for(i=1;i<=B;i++) cap[i]=c[i];
        n=N;m=B;
        if(maxmatch()==N)
        {
            if(ans>r-l+1) ans=r-l+1;
            ++l;
        } else ++r;
    }
    printf("%d\n",ans);
}

话说从上次回来后就很久没做了,一直在忙落下的作业和实验,要坚持啊.


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter