• HDU1281 棋盘游戏(二分匹配+找必要的点)


    题意:

    给你一个n*m的地图和k个地图上可以放车的点

    让你求出最多放多少个车和哪些点是必要的(没有它匹配数就会减少)

    思路:

    匈牙利求最大匹配,然后一个一个的删除匹配点进行匹配,

    如果删除该点后匹配数减少,则这个点就是必要的

    代码:

    一开始用vector要记删除的点参数比较麻烦

    /* ***********************************************
    //Author        :devil
    //Created Time  :2016/5/10 17:22:52
    //************************************************ */
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <set>
    #include <map>
    #include <string>
    #include <cmath>
    #include <stdlib.h>
    using namespace std;
    const int N=105;
    vector<int>eg[N];
    int link[N],used[N],dx;
    bool vis[N];
    bool dfs(int u,int f)
    {
        for(int i=0;i<eg[u].size();i++)
        {
            int v=eg[u][i];
            if(!f&&u==dx&&v==used[dx]) continue;
            if(!vis[v])
            {
                vis[v]=1;
                if(link[v]==-1||dfs(link[v],f))
                {
                    link[v]=u;
                    if(f) used[u]=v;
                    return 1;
                }
            }
        }
        return 0;
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        int n,m,k,x,y,cas=0;
        while(~scanf("%d%d%d",&n,&m,&k))
        {
            memset(link,-1,sizeof(link));
            for(int i=1;i<=100;i++)
                eg[i].clear();
            memset(used,0,sizeof(used));
            while(k--)
            {
                scanf("%d%d",&x,&y);
                eg[x].push_back(y);
            }
            int ma=0,ans=0;
            for(int i=1;i<=n;i++)
            {
                memset(vis,0,sizeof(vis));
                ma+=dfs(i,1);
            }
            for(int i=1;i<=n;i++)
            {
                if(used[i])
                {
                    memset(link,-1,sizeof(link));
                    int now=0;
                    dx=i;
                    for(int j=1;j<=n;j++)
                    {
                        memset(vis,0,sizeof(vis));
                        now+=dfs(j,0);
                    }
                    if(now!=ma) ans++;
                }
            }
            printf("Board %d have %d important blanks for %d chessmen.
    ",++cas,ans,ma);
        }
        return 0;
    }

    然后索性用邻接矩阵写了。。

    /* ***********************************************
    //Author        :devil
    //Created Time  :2016/5/10 17:23:18
    //************************************************ */
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <set>
    #include <map>
    #include <string>
    #include <cmath>
    #include <stdlib.h>
    using namespace std;
    const int N=105;
    int link[N],used[N],n,m,k;
    bool mp[N][N],vis[N];
    bool dfs(int u,int f)
    {
        for(int i=1;i<=m;i++)
        {
            if(mp[u][i]&&!vis[i])
            {
                vis[i]=1;
                if(link[i]==-1||dfs(link[i],f))
                {
                    link[i]=u;
                    if(f) used[u]=i;
                    return 1;
                }
            }
        }
        return 0;
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        int x,y,cas=0;
        while(~scanf("%d%d%d",&n,&m,&k))
        {
            memset(link,-1,sizeof(link));
            memset(mp,0,sizeof(mp));
            memset(used,0,sizeof(used));
            while(k--)
            {
                scanf("%d%d",&x,&y);
                mp[x][y]=1;
            }
            int ma=0,ans=0;
            for(int i=1;i<=n;i++)
            {
                memset(vis,0,sizeof(vis));
                ma+=dfs(i,1);
            }
            for(int i=1;i<=n;i++)
            {
                if(used[i])
                {
                    memset(link,-1,sizeof(link));
                    int now=0;
                    mp[i][used[i]]=0;
                    for(int j=1;j<=n;j++)
                    {
                        memset(vis,0,sizeof(vis));
                        now+=dfs(j,0);
                    }
                    mp[i][used[i]]=1;
                    if(now!=ma) ans++;
                }
            }
            printf("Board %d have %d important blanks for %d chessmen.
    ",++cas,ans,ma);
        }
        return 0;
    }
  • 相关阅读:
    win10如何将现有的桌面壁纸找出来
    js 显示网站当前访客是几位访客
    SELECT DISTINCT 取列中所有不重复的值
    mysql5.6和8.0中都没有len()函数,获取字符串长度的函数是length()
    TOP 子句用于规定要返回的记录的数目。
    sqlmap提示you haven't updated sqlmap for more than 126 days!!!
    利用代码生成a-z的所有字母的指定长度的组合字典
    生成图形验证码 将图形验证码流写到前台
    JDK历史版本
    mysql 数据库隔离级别
  • 原文地址:https://www.cnblogs.com/d-e-v-i-l/p/5478596.html
Copyright © 2020-2023  润新知