一些二分匹配的题

/*poj1469简单的二分匹配*/

#include<stdio.h>
#include<string.h>
int map[1005][1005],vis[2000],match[2000];
int n,m;
int dfs(int u)
{
    int i,j;
    for(i=1;i<=n;i++)//根据课
    {
        if(!vis[i]&&map[u][i])
        {
            vis[i]=1;
            if(match[i]==-1||dfs(match[i]))
            {
                match[i]=u;
                return 1;
            }
        }
    }
    return 0;
}
int main()
{
    int i,j,t;
    scanf("%d",&t);
    while(t--)
    {
        memset(map,0,sizeof(map));
        scanf("%d%d",&m,&n);//m人 n课
        for(i=1;i<=m;i++)
        {
            int l,x;
            scanf("%d",&l);
            while(l--)
            {
                scanf("%d",&x);
                map[i][x]=1;
            }
        }
        int ans=0;
        memset(match,-1,sizeof(match));
        for(i=1;i<=m;i++)
        {
            memset(vis,0,sizeof(vis));
            if(dfs(i))
                ans++;
        }
        if(ans==m)
            printf("YES\n");
        else printf("NO\n");
    }
}

/**poj2446*/
/*第一次交数组开小了 ,改好就A了,哈哈,开心*/

#include<stdio.h>
#include<string.h>
int map[50][50],g[1205][1205],n,m,k,sum,vis[3000],match[3000];
void makemap()
{
    memset(g,0,sizeof(g));
    int i,j;
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=m;j++)
        {
            if(map[i][j]&&(i+1)<=n)
                g[map[i][j]][map[i+1][j]]=1;//下面的
            if(map[i][j]&&(i-1)>=1)
                g[map[i][j]][map[i-1][j]]=1;//上面的
            if(map[i][j]&&(j+1)<=m)
                g[map[i][j]][map[i][j+1]]=1;//右面的
            if(map[i][j]&&(j-1)>=1)
                g[map[i][j]][map[i][j-1]]=1;//左面的
        }
    }
}
int dfs(int u)
{
    int i,j;
    for(i=1;i<sum;i++)
    {
        if(g[u][i]&&!vis[i])
        {
            vis[i]=1;
            if(match[i]==-1||dfs(match[i]))
            {
                match[i]=u;
                return 1;
            }
        }
    }
    return 0;
}
int main()
{
    int i,j;
    while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    {
        sum=1;
        for(i=1;i<=n;i++)
            for(j=1;j<=m;j++)
                map[i][j]=sum++;
        for(i=1;i<=k;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            map[y][x]=0;
        }
        makemap();
        int ans=0;
        memset(match,-1,sizeof(match));
        for(i=1;i<sum;i++)
        {
            memset(vis,0,sizeof(vis));
            if(dfs(i))
            {
                ans++;
            }
        }
        if(ans+k==(n*m))
            printf("YES\n");
        else printf("NO\n");
    }
}
//最大独立集
//hdu1068
#include<stdio.h>
#include<string.h>
struct node
{
    int x;
    int next;
}edge[2000];
int head[2000],n,vis[2000],match[2000];
int index;
void add(int xx,int yy)
{
    edge[index].x=yy;
    edge[index].next=head[xx];
    head[xx]=index++;
}
int dfs(int u)
{
    int i,j;
    for(i=head[u];i!=-1;i=edge[i].next)
    {
        int tmp=edge[i].x;
        if(!vis[tmp])
        {
            vis[tmp]=1;
            if(match[tmp]==-1||dfs(match[tmp]))
            {
                match[tmp]=u;
                return 1;
            }
        }
    }
    return 0;
}
int main()
{
    int i,j,t;
    while(scanf("%d",&n)!=EOF)
    {
        memset(head,-1,sizeof(head));
        memset(match,-1,sizeof(match));
        index=0;
        for(i=0;i<n;i++)
        {
            scanf("%d: (%d)",&j,&t);
            while(t--)
            {
                int l;
                scanf("%d",&l);
                add(j,l);
            }
        }
        int ans=0;
        for(i=0;i<n;i++)
        {
            memset(vis,0,sizeof(vis));
            if(dfs(i))
                ans++;
        }
        if(ans%2)ans+=1;
        printf("%d\n",n-ans/2);//最大独立集=顶点总数-二分图最大匹配
    }
}

/*
最小顶点覆盖 == 最大匹配(双向图)/2;hdu1054
要双向图
*/

#include<stdio.h>
#include<string.h>
struct node
{
    int v;
    int next;
}edge[20000];
int vis[2000],head[2000],match[2000];
int n,m,index;
void add(int x,int y)
{
    edge[index].v=y;
    edge[index].next=head[x];
    head[x]=index++;
}
int dfs(int u)
{
    int i,j;
    for(i=head[u];i!=-1;i=edge[i].next)
    {
        int tmp=edge[i].v;
        if(!vis[tmp])
        {
            vis[tmp]=1;
            if(match[tmp]==-1||dfs(match[tmp]))
            {
                match[tmp]=u;
                return 1;
            }
        }
    }
    return 0;
}
int main()
{
    int i,j,t;
    while(scanf("%d",&n)!=EOF)
    {
        index=1;
        memset(head,-1,sizeof(head));
        memset(match,-1,sizeof(match));
        for(i=0;i<n;i++)
        {
            int l;
            scanf("%d:(%d)",&l,&t);
            while(t--)
            {
                int x;
                scanf("%d",&x);
                add(l,x);
                add(x,l);
            }
        }
        int ans=0;
        for(i=0;i<n;i++)
        {
            memset(vis,0,sizeof(vis));
            if(dfs(i))
            {
                ans++;
            }
        }
        printf("%d\n",ans/2);
    }
}

				
时间: 2024-10-10 10:35:06

一些二分匹配的题的相关文章

poj3041(二分匹配简单题)

题目链接:http://poj.org/problem?id=3041 Asteroids Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14022   Accepted: 7629 Description Bessie wants to navigate her spaceship through a dangerous asteroid field in the shape of an N x N grid (1 <

UVALive 6525 Attacking rooks 二分匹配 经典题

题目链接:option=com_onlinejudge&Itemid=8&page=show_problem&problem=4536">点击打开链接 题意: 给定n*n的棋盘, 能够在'.'上摆 象棋中的车(X是墙壁) 使得随意两个车都不能互相攻击到 问:最多能摆多少个车. 思路: 二分匹配 1.若没有X.那么做法就是 X点集为行,Y点集为列,对于图上的每一个点所在的行和列(x,y) 建一条边 x->y 2.有了X,那么对于每一个点所在的上方能接触到的X必须

COURSES 赤裸裸的二分匹配大水题

COURSES 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <string> 7 #include <vector> 8 #include <set> 9 #include <map> 10 #include &l

UVA5874 Social Holidaying 二分匹配

二分匹配简单题,看懂题意,建图比较重要. #include<stdio.h> #include<string.h> #define maxn 1100 int map[maxn][maxn]; int a[maxn],b[maxn],match[maxn],vis[maxn]; int n,m; void makemap() { int i,j,k; for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { for(k=1;k<=m;k++)

hdu 2255 二分图带权匹配 模板题

模板+注解在 http://blog.csdn.net/u011026968/article/details/38276945 hdu 2255 代码: //KM×î´ó×îСƥÅä #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; #define INF 0x0fffffff const int MAXN

HDU2063(二分匹配入门模板题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2063 过山车 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 9322    Accepted Submission(s): 4108 Problem Description RPG girls今天和大家一起去游乐场玩,终于可以坐上梦寐以求

POJ 1466 Girls and Boys 黑白染色 + 二分匹配 (最大独立集) 好题

有n个人, 其中有男生和女生,接着有n行,分别给出了每一个人暗恋的对象(不止暗恋一个) 现在要从这n个人中找出一个最大集合,满足这个集合中的任意2个人,都没有暗恋这种关系. 输出集合的元素个数. 刚开始想,把人看成顶点,若有暗恋的关系,就连一条边,构成一个图 独立集的概念:一个图中两两互不相连的顶点集合 所以这道题,就是要求最大独立集 有:最大独立集+最小顶点覆盖=|V|(顶点的总个数) 那就求最小顶点覆盖了 根据题意: 暗恋的对象性别不同,所以a暗恋b,b暗恋c,c暗恋a这种关系不可能存在 也

HDU5943 Kingdom of Obsession(思路题+二分匹配)

题意: 给你两个数n,s(1e9),问你能否使得s+1--s+n和1--n全部匹配 每个数只能匹配他的因子 思路: 要匹配的这一段数中非重合部分最多有1个素数,也就是说n和s不能同时很大 我打了1e9的素数间隔表,发现最大间距才280多.. 然后索性直接当n和s都大于500的时候就输出no就可以了 符合条件的数非重合部分最多500个,二分匹配一下 /* *********************************************** Author :devil **********

HDU 3861 The King’s Problem (强连通+二分匹配)

题目地址:HDU 3861 这题虽然是两个算法结合起来的.但是感觉挺没意思的..结合的一点也不自然,,硬生生的揉在了一块...(出题者不要喷我QAQ.) 不过这题让我发现了我的二分匹配已经好长时间没用过了..都快忘了..正好在省赛之前又复习了一下. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm>