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

ACM -二分图题目小结(更新中)

时间:2014-05-04 11:20:45      阅读:390      评论:0      收藏:0      [点我收藏+]

标签:style   blog   class   code   tar   color   

暂时只包括与最大匹配相关的问题。

求最大独立集,最小路径覆盖等等大多数题目都可以转化为求最大匹配用匈牙利算法解决。

 

1.最大匹配(边集)

此类问题最直接,直接用匈牙利算法即可。

 HDU 2063  过山车

http://acm.hdu.edu.cn/showproblem.php?pid=2063

二分图最大匹配模版题。

ZOJ 1654 - Place the Robots

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1654

易想到求最大独立集但是时间复杂度太高,可以变成二分图最大匹配来做,重在建模。

 

2.最小路径覆盖(边集)

对于不存在孤立的点的图,|最小路径覆盖|+|最大匹配|=V(顶点数)

因此可以通过求最大匹配来做。

这个等式在DAG图中也成立,详见http://www.cnblogs.com/jackiesteed/articles/2043934.html。对于DAG图可以拆点来做。

HDU 1151 Air Raid

http://acm.hdu.edu.cn/showproblem.php?pid=1151

bubuko.com,布布扣
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstdlib>
 6 #include<cstdio>
 7 #include<vector>
 8 #define MAXN 1005
 9 using namespace std;
10 bool gl[MAXN][MAXN];
11 int link[MAXN];
12 int n;
13 bool vis[MAXN];
14 
15 bool match(int x)
16 {
17     for(int i=1; i<=n; ++i)
18         if(gl[x][i]&&!vis[i])
19         {
20             vis[i]=true;
21             if(link[i]==-1||match(link[i]))
22             {
23                 link[i]=x;
24                 return true;
25             }
26         }
27     return false;
28 }
29 int main()
30 {
31     int T;
32     scanf("%d",&T);
33     while(T--)
34     {  int m;
35         scanf("%d%d",&n,&m);
36         memset(gl,0,sizeof(gl));
37         for(int i=0;i<m;++i)
38         {
39             int x,y;
40             scanf("%d%d",&x,&y);
41             gl[x][y]=true;
42         }
43         int res=0;
44         memset(link,-1,sizeof(link));
45         for(int i=1; i<=n; ++i)
46         {
47             memset(vis,0,sizeof(vis));
48             if(match(i)) res++;
49         }
50         printf("%d\n",n-res);
51     }
52     return 0;
53 }
View Code

求DAG的最小路径覆盖。

 

3.最小顶点覆盖(点集)

在二分图中|最大匹配|=|最小顶点覆盖|,但是注意要解决的问题本身并不是最大匹配,理解了问题本身才能建模。

HDU 1054  Strategic Game

http://acm.hdu.edu.cn/showproblem.php?pid=1054

此题可以用树形DP来做也可以用求最小顶点覆盖,但是时间较慢。拆点,改成双向图,用邻接表。

bubuko.com,布布扣
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<vector>
#define MAXN 1505
using namespace std;
vector<int> gl[MAXN];
int link[MAXN];
int n;
bool vis[MAXN];
void init()
{
    memset(link,-1,sizeof(link));
    memset(vis,0,sizeof(vis));
}

bool match(int x)
{
    for(int i=0; i<gl[x].size(); ++i)
    {
        int &u=gl[x][i];
        if(!vis[u])
        {
            vis[u]=true;
            if(link[u]==-1||match(link[u]))
            {
                link[u]=x;
                return true;
            }
        }
    }

    return false;
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        memset(gl,0,sizeof(gl));
        for(int i=0; i<n; ++i)  gl[i].clear();
        for(int i=0; i<n; ++i)
        {
            int now,t,cn;
            scanf("%d:",&now);
            scanf("(%d)",&cn);
            while(cn--)
            {
                scanf("%d",&t);
                gl[now].push_back(t);
                gl[t].push_back(now);
            }
        }
        init();
        int res=0;
        for(int i=0; i<n; ++i)
        {
            memset(vis,0,sizeof(vis));
            if(match(i)) res++;
        }
        printf("%d\n",res/2);
    }
    return 0;
}
View Code

HDU 1150  Machine Schedule

http://acm.hdu.edu.cn/showproblem.php?pid=1150

bubuko.com,布布扣
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<vector>
#define MAXN 1005
using namespace std;
bool gl[MAXN][MAXN];
int link[MAXN];
int n,m;
bool vis[MAXN];

bool match(int x)
{
    for(int i=1; i<=m; ++i)
        if(gl[x][i]&&!vis[i])
        {
            vis[i]=true;
            if(link[i]==-1||match(link[i]))
            {
                link[i]=x;
                return true;
            }
        }
    return false;
}
int main()
{
    int t;
    while(scanf("%d",&n)&&n)
    {
        scanf("%d%d",&m,&t);
        memset(gl,0,sizeof(gl));
        for(int i=0; i<t; ++i)
        {
            int x,y,z;
            scanf("%d%d%d",&z,&x,&y);
            gl[x][y]=true;
        }
        int res=0;
        memset(link,-1,sizeof(link));
        for(int i=1; i<=n; ++i)
        {
            memset(vis,0,sizeof(vis));
            if(match(i)) res++;
        }
        printf("%d\n",res);
    }
    return 0;
}
View Code

 


4.最大独立集(点集)

|最大独立集|+|最小顶点覆盖|=V

求最大独立集是NP问题,但是在二分图中|最大匹配|=|最小顶点覆盖|,所以这个问题也有了高效的算法。

 HDU 1045  Fire Net

http://acm.hdu.edu.cn/showproblem.php?pid=1045

这个可以暴力求最大独立集。

HDU 2768  Cat vs. Dog

http://acm.hdu.edu.cn/showproblem.php?pid=2768

根据矛盾之间建图,求最大独立集。

HDU 1068  Girls and Boys

http://acm.hdu.edu.cn/showproblem.php?pid=1068

题意很明显就是求二分图最大独立集。但是由于没说给的是男还是女,所以需要拆点,得到的最大匹配数要除以2,再套用公式得最大独立集。

bubuko.com,布布扣
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstdlib>
 6 #include<cstdio>
 7 #include<vector>
 8 #define MAXN 1005
 9 using namespace std;
10 bool gl[MAXN][MAXN];
11 int link[MAXN];
12 int n;
13 bool vis[MAXN];
14 void init()
15 {
16     memset(link,-1,sizeof(link));
17     memset(vis,0,sizeof(vis));
18 }
19 
20 bool match(int x)
21 {
22     for(int i=0; i<n; ++i)
23         if(gl[x][i]&&!vis[i])
24         {
25             vis[i]=true;
26             if(link[i]==-1||match(link[i]))
27             {
28                 link[i]=x;
29                 return true;
30             }
31         }
32     return false;
33 }
34 int main()
35 {
36     while(scanf("%d",&n)!=EOF)
37     {
38         memset(gl,0,sizeof(gl));
39         for(int i=0; i<n; ++i)
40         {
41             int now,t,cn;
42             scanf("%d: ",&now);
43             scanf("(%d) ",&cn);
44             while(cn--)
45             {
46                 scanf("%d",&t);
47                 gl[now][t]=true;
48             }
49         }
50         init();
51         int res=0;
52         for(int i=0; i<n; ++i)
53         {
54             memset(vis,0,sizeof(vis));
55             if(match(i)) res++;
56         }
57         printf("%d\n",(n*2-res)/2);
58     }
59     return 0;
60 }
View Code

 

 

5.判断二分图

此类问题可以BFS或DFS解决,注意图可能不连通。

 HDU 4751 Divide Groups

http://acm.hdu.edu.cn/showproblem.php?pid=4751

根据不互相认识这一关系连边,判断二分图。

 

 

 

ACM -二分图题目小结(更新中),布布扣,bubuko.com

ACM -二分图题目小结(更新中)

标签:style   blog   class   code   tar   color   

原文地址:http://www.cnblogs.com/kkkwjx/p/3705556.html

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