二分图入门题集

最近遇到二分图匹配的题目,发现不怎么会,重新把之前的题目看了看,做下总结吧。

http://poj.org/problem?id=1469  纯纯的二分图的最大匹配

 

 1 #include <iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<algorithm>

 5 #include<stdlib.h>

 6 #include<vector>

 7 #include<queue>

 8 #include<cmath>

 9 using namespace std;

10 vector<int>pa[410];

11 int vis[410],mat[410];

12 int find(int u)

13 {

14     int i;

15     for(i = 0 ; i < (int)pa[u].size() ; i++)

16     {

17         int v = pa[u][i];

18         if(vis[v]) continue;

19         vis[v] = 1;

20         if(mat[v]==0||find(mat[v]))

21         {

22             mat[v] = u;

23             return 1;

24         }

25     }

26     return 0;

27 }

28 int main()

29 {

30     int t,n,m,i,j;

31     cin>>t;

32     while(t--)

33     {

34         memset(mat,0,sizeof(mat));

35         for(i = 1; i <= 400 ; i++)

36         pa[i].clear();

37         scanf("%d%d",&m,&n);

38         for(i = 1; i <= m ;i++)

39         {

40             int k,u;

41             scanf("%d",&k);

42             for(j = 1; j <= k ;j++)

43             {

44                 scanf("%d",&u);

45                 pa[i].push_back(m+u);

46             }

47         }

48         int s=0;

49         for(i = 1; i <= m ;i++)

50         {

51             memset(vis,0,sizeof(vis));

52             if(find(i))

53             s++;

54         }

55         if(s==m)

56         puts("YES");

57         else

58         puts("NO");

59     }

60     return 0;

61 }
View Code

http://poj.org/problem?id=3041 纯纯的最小点覆盖 把点拆成边  用最少的点覆盖所有的边

 1 #include <iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<algorithm>

 5 #include<stdlib.h>

 6 #include<vector>

 7 #include<queue>

 8 #include<cmath>

 9 using namespace std;

10 #define N 1010

11 vector<int>pa[N];

12 bool f[N];

13 int vis[N],mat[N];

14 int find(int u)

15 {

16     int i;

17     for(i = 0 ; i < (int)pa[u].size() ; i++)

18     {

19         int v = pa[u][i];

20         if(vis[v]) continue;

21         vis[v] = 1;

22         if(mat[v]==0||find(mat[v]))

23         {

24             mat[v] = u;

25             return 1;

26         }

27     }

28     return 0;

29 }

30 int main()

31 {

32     int n,m,i;

33     while(scanf("%d%d",&n,&m)!=EOF)

34     {

35         memset(mat,0,sizeof(mat));

36         memset(f,0,sizeof(f));

37         for(i = 1; i <= 1000 ; i++)

38         pa[i].clear();

39         for(i = 1; i <= m ;i++)

40         {

41             int v,u;

42             scanf("%d%d",&u,&v);

43             pa[u].push_back(v);

44             f[u] = 1;

45         }

46         int s=0;

47         for(i = 1; i <= n ;i++)

48         {

49             if(!f[i]) continue;

50             memset(vis,0,sizeof(vis));

51             if(find(i))

52             s++;

53         }

54         printf("%d\n",s);

55     }

56     return 0;

57 }
View Code

http://poj.org/problem?id=1422 纯纯的最小路径覆盖 总结点-最大匹配

 1 #include <iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<algorithm>

 5 #include<stdlib.h>

 6 #include<vector>

 7 #include<queue>

 8 #include<cmath>

 9 using namespace std;

10 #define N 1010

11 vector<int>pa[N];

12 bool fx[N],fy[N];

13 int vis[N],mat[N];

14 int find(int u)

15 {

16     int i;

17     for(i = 0 ; i < (int)pa[u].size() ; i++)

18     {

19         int v = pa[u][i];

20         if(vis[v]) continue;

21         vis[v] = 1;

22         if(mat[v]==0||find(mat[v]))

23         {

24             mat[v] = u;

25             return 1;

26         }

27     }

28     return 0;

29 }

30 int main()

31 {

32     int n,m,i,t;

33     scanf("%d",&t);

34     while(t--)

35     {

36         scanf("%d%d",&n,&m);

37         memset(mat,0,sizeof(mat));

38         for(i = 1; i <= 1000 ; i++)

39         pa[i].clear();

40         for(i = 1; i <= m ;i++)

41         {

42             int v,u;

43             scanf("%d%d",&u,&v);

44             pa[u].push_back(v+n);

45         }

46         int s = 0;

47         for(i = 1; i <= n ;i++)

48         {

49             memset(vis,0,sizeof(vis));

50             if(find(i))

51                 s++;

52         }

53         printf("%d\n",n-s);

54     }

55     return 0;

56 }
View Code

http://poj.org/problem?id=3020 这题可以最小路径来做

以前拆点做的 这次没有拆点 直接找最大匹配 以为一根天线覆盖2点 正好是一对匹配 所以最大的匹配的时候肯定是用天线最少的时候 ans = 总结点-2*最大匹配+最大匹配

 1 #include <iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<algorithm>

 5 #include<stdlib.h>

 6 #include<cmath>

 7 #include<vector>

 8 using namespace std;

 9 char c[42][12];

10 vector<int>pa[410];

11 int vis[420],vv[420],mat[420];

12 int find(int u)

13 {

14     int i;

15     for(i = 0 ;i < (int)pa[u].size() ; i++)

16     {

17         int v = pa[u][i];

18         if(vv[v]) continue;

19         vv[v] = 1;

20         if(mat[v]==0||find(mat[v]))

21         {

22             mat[v] = u;

23             return 1;

24         }

25     }

26     return 0;

27 }

28 void dfs(int u,int f)

29 {

30     vis[u] = f;

31     int i;

32     for(i = 0 ;i < (int)pa[u].size(); i++)

33     {

34         int v = pa[u][i];

35         if(vis[v]) continue;

36         dfs(v,f*(-1));

37     }

38 }

39 int main()

40 {

41     int n,i,j,w,h;

42     cin>>n;

43     while(n--)

44     {

45         memset(c,0,sizeof(c));

46         memset(vis,0,sizeof(vis));

47         memset(vv,0,sizeof(vv));

48         memset(mat,0,sizeof(mat));

49         memset(pa,0,sizeof(pa));

50         cin>>w>>h;

51         for(i =1; i <= w ; i++)

52             for(j = 1; j <= h ; j++)

53             cin>>c[i][j];

54         int s=0;

55         for(i = 1; i <= w ; i++)

56             for(j = 1 ; j <= h ; j++)

57             {

58                 if(c[i][j]=='*') s++;

59                 if(c[i][j]=='*'&&c[i+1][j]=='*')

60                     pa[(i-1)*h+j].push_back(i*h+j);

61                 if(c[i][j]=='*'&&c[i][j+1]=='*')

62                     pa[(i-1)*h+j].push_back((i-1)*h+j+1);

63                 if(c[i][j]=='*'&&c[i][j-1]=='*')

64                 pa[(i-1)*h+j].push_back((i-1)*h+j-1);

65                 if(c[i][j]=='*'&&c[i-1][j]=='*')

66                 pa[(i-1)*h+j].push_back((i-2)*h+j);

67             }

68         int ans=0;

69         for(i = 1; i <= w ; i++)

70             for(j = 1 ;j <= h ;j++)

71             {

72                 int k = (i-1)*h+j;

73                 if(c[i][j]!='*'||vis[k]) continue;

74                 dfs(k,1);

75             }

76         for(i = 1; i <= w*h ; i++)

77         {

78             memset(vv,0,sizeof(vv));

79             if(vis[i]==1)

80             {

81                 if(find(i)) ans++;

82             }

83         }

84         cout<<s-ans<<endl;

85     }

86     return 0;

87 }
View Code

http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=1925 这是09年区域赛的一道题 是求减去最小的边使得图里没有奇圈

这样 这题就可以利用二分图的性质来做 因为二分图是不含奇圈的 15个点 (1<<15)种分法 看哪种方法所需删边最少

 1 #include <iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<algorithm>

 5 #include<stdlib.h>

 6 #include<vector>

 7 #include<cmath>

 8 #include<queue>

 9 using namespace std;

10 #define INF 0xfffffff

11 bool f[16];

12 struct node

13 {

14     int u,v;

15 }p[310];

16 int main()

17 {

18     int t,i,j,n,m;

19     cin>>t;

20     while(t--)

21     {

22        cin>>n>>m;

23        for(i = 1; i <= m ;i++)

24        {

25            cin>>p[i].u>>p[i].v;

26        }

27        int minz = INF;

28        for(i = 0 ;i < (1<<n) ; i++)

29        {

30            int cnt=0;

31            memset(f,0,sizeof(f));

32            for(j = 0 ;j < n ; j++)

33            {

34                if(i&(1<<j))

35                    f[j] = 1;

36            }

37            for(j = 1 ; j <= m ; j++)

38            if(f[p[j].u]==f[p[j].v])

39            cnt++;

40            minz = min(minz,cnt);

41        }

42        cout<<minz<<endl;

43     }

44     return 0;

45 }

46  

47 

48 

49 

50 /**************************************

51     Problem id    : SDUT OJ 1925 

52     User name    : shang 

53     Result        : Accepted 

54     Take Memory    : 476K 

55     Take Time    : 30MS 

56     Submit Time    : 2014-02-19 10:51:51  

57 **************************************/
View Code

 

你可能感兴趣的:(二分图)