码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2016-05-10 18:30:34      阅读:133      评论:0      收藏:0      [点我收藏+]

标签:

题意:

给你一个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.\n",++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.\n",++cas,ans,ma);
    }
    return 0;
}

 

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

标签:

原文地址:http://www.cnblogs.com/d-e-v-i-l/p/5478596.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!