zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    Codeforces 876C Classroom Watch:枚举
    Codeforces 876B Divisiblity of Differences:数学【任意两数之差为k的倍数】
    BZOJ 3943 [Usaco2015 Feb]SuperBull:最大生成树
    BZOJ 3391 [Usaco2004 Dec]Tree Cutting网络破坏:dfs【无根树 节点分枝子树大小】
    markdown常用数学符号小结
    BZOJ3211花神游历各国-线段树&树状数组-(HDU4027同类型)
    一维二维树状数组写法总结
    hdu4352-XHXJ's LIS状压DP+数位DP
    常用Git命令以及出现的状况ing
    bitset简单用法
  • 原文地址:https://www.cnblogs.com/d-e-v-i-l/p/5478596.html
Copyright © 2011-2022 走看看