zoukankan      html  css  js  c++  java
  • 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.
    ",cas++,sum,ans);
        }
        return 0;
    }
  • 相关阅读:
    JS中怎样获取当前日期的前一个月和后一个月的日期字符串
    JS中怎样将时间字符串转换成Date并比较大小
    Java中判断两个Date时间段是否有交集的方法
    gRPC中Java和node进行异构通信-互为客户端和服务端
    ffmpeg external libraries 下载地址
    libsvtav1 的 qp 和比特率对照表
    libsvtav1 AV1 编码速度比 libaom 大大提升
    ffmpeg windows 最新编译内部版本下载地址变更
    解开获取 aria2c 帮助信息的误区
    frei0r 过了好几年增加 aech0r 滤镜
  • 原文地址:https://www.cnblogs.com/bitch1319453/p/4799167.html
Copyright © 2011-2022 走看看