hdu 1281 二分图残量增广

http://acm.hdu.edu.cn/showproblem.php?pid=1281

每行每列最多放置一个车,所以可以把行号和列号当成点,给定的点当成边进行最大匹配,得到的答案就是最大放置数了

然后,还要求重要点——转化为删除边后得到的最大匹配数是否发生变化的问题

易知重要点一定是模型中产生最大匹配时的边,所以我们枚举这样的边,尝试着删除判断情况

较优的做法是删边时将两个标号标记为未匹配,然后禁用这条边,在原有的基础上进行增广,若没有找到新的增广路,则重要点数+1,把两个标记复原

若找到了新的增广路,则我们又得到了一个最大匹配,这里就没有将两个标号复原了

之后将边的禁用取消,枚举下一条边

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=208;
struct fuck{
    int v,next;
}edge[maxn*maxn];
int tol;
int head[maxn];
void init()
{
    tol=0;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v)
{
    edge[tol].v=v;
    edge[tol].next=head[u];
    head[u]=tol++;
}
int pre[maxn];
int bian[maxn];
bool vis[maxn];
bool ban[maxn*maxn];
bool used[maxn];
bool find(int u)
{
    int i,v;
    for(i=head[u];i!=-1;i=edge[i].next)
    {
        v=edge[i].v;
        if(vis[v]||ban[i])    continue;
        vis[v]=true;
        if(pre[v]==-1||find(pre[v]))
        {
            pre[v]=u;
            bian[v]=i;
            return true;
        }
    }
    return false;
}
int  hungary(int n)
{
    int i,ans=0;
    memset(pre,-1,sizeof(pre));
    for(i=1;i<=n;i++)
    {
        memset(vis,false,sizeof(vis));
        if(find(i))    ans++;
    }
    return ans;
}
bool ck(int n)
{
    int u;
    for(u=1;u<=n;u++)
    {
        if(used[u])    continue;
        memset(vis,false,sizeof(vis));
        if(find(u))
        {
            used[u]=true;
            return true;
        }
    }
    return false;
}
int main()
{
    int i,j,n,m,k,u,v;
    int cas=1;
    while(scanf("%d%d%d",&n,&m,&k)==3)
    {
        init();
        for(i=1;i<=k;i++)
        {
            scanf("%d%d",&u,&v);
            addedge(u,v+n);
        }
        memset(ban,false,sizeof(ban));
        int ans=hungary(n);
        int sum=0;
        memset(used,false,sizeof(used));
        for(j=n+1;j<=n+m;j++)    if(pre[j]!=-1) used[pre[j]]=true;
        for(i=n+1;i<=n+m;i++)
        {
            if(pre[i]==-1)    continue;
            int bitch=bian[i];
            int shit=pre[i];
            ban[bian[i]]=true;
            pre[i]=-1;
            used[shit]=false;
            if(!ck(n))
            {
                sum++;
                pre[i]=shit;
                used[shit]=true;
            }        
            ban[bitch]=false;
        }    
        printf("Board %d have %d important blanks for %d chessmen.\n",cas++,sum,ans);
    }
    return 0;
}

 

posted on 2015-09-10 21:27  此剑之势愈斩愈烈  阅读(155)  评论(0编辑  收藏  举报

导航