HDU 1054 Strategic Game(二分图匈牙利算法,最小点覆盖数,vector实现)

题目:

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

 

关于匈牙利算法的博客讲解

https://www.cnblogs.com/shenben/p/5573788.html

https://blog.csdn.net/qq_40938077/article/details/80410356 

(摘自上面博客)

 1 #include<bits/stdc++.h>
 2 #define MAXN 9999
 3 using namespace std;
 4 int nx,ny;//nx表示二分图左边顶点的个数,ny表示二分图右边顶点的个数
 5 int m;//m代表边的条数
 6 int cx[MAXN],cy[MAXN];//如果有cx[i]=j,则必有cy[j]=i,说明i点和j点能够匹配
 7 int x,y;//x点到y点有边
 8 int e[MAXN][MAXN];//邻接矩阵
 9 int visited[MAXN];//标记数组,标记的永远是二分图右边的顶点
10 int ret;//最后结果
11 int point(int u)//这个函数的作用是寻找增广路和更新cx,xy数组,如果找到了增广路,函数返回1,找不到,函数返回0。
12 {
13     for(int v=1;v<=ny;v++)//依次遍历右边的所有顶点
14     {
15         if(e[u][v]&&!visited[v])//条件一:左边的u顶点和右边的v顶点有连通边,条件二:右边的v顶点在没有被访问过,这两个条件必须同时满足
16         {
17             visited[v]=1;//将v顶点标记为访问过的
18             if(cy[v]==-1||point(cy[v]))//条件一:右边的v顶点没有左边对应的匹配的点,条件二:以v顶点在左边的匹配点为起点能够找到一条增广路(如果能够到达条件二,说明v顶点在左边一定有对应的匹配点)。
19             {
20                 cx[u]=v;//更新cx,cy数组
21                 cy[v]=u;
22                 return 1;
23             }
24         }
25     }
26     return 0;//如果程序到达了这里,说明对右边所有的顶点都访问完了,没有满足条件的。
27 }
28 int main()
29 {
30     while (cin>>m>>nx>>ny)
31     {
32         memset(cx,-1,sizeof(cx));//初始化cx,cy数组的值为-1
33         memset(cy,-1,sizeof(cy));
34         memset(e,0,sizeof(e));//初始化邻接矩阵
35         ret=0;
36         while (m--)//输入边的信息和更新邻接矩阵
37         {
38             cin>>x>>y;
39             e[x][y]=1;
40         }
41         for(int i=1;i<=nx;i++)//对二分图左边的所有顶点进行遍历
42         {
43             if(cx[i]==-1)//如果左边的i顶点还没有匹配的点,就对i顶点进行匹配
44             {
45                 memset(visited,0,sizeof(visited));//每次进行point时,都要对visited数组进行初始化
46                 ret+=point(i);//point函数传入的参数永远是二分图左边的点
47             }
48         }
49         cout<<ret<<endl;
50     }
51  
52 }

 

AC代码:

 1 #include<cstdio.>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<vector>
 5 using namespace std;
 6 
 7 const int maxn=1510;
 8 int linker[maxn];
 9 int vis[maxn];
10 vector<int>Map[maxn];
11 int n;
12 
13 bool point(int u)
14 {
15     for(int i=0;i<Map[u].size();i++)
16     {
17         if(!vis[Map[u][i]])//如果没有访问过这个点 
18         {
19             vis[Map[u][i]]=1;//标记访问 
20             if(linker[Map[u][i]]==-1||point(linker[Map[u][i]]))
21             {//如果这条路这个点没有走过 
22                 linker[Map[u][i]]=u;
23                 return 1;
24             }
25         }
26     }
27     return 0;
28 }
29 int hungary()//匈牙利 
30 {
31     int res=0;
32     memset(linker,-1,sizeof(linker));
33     for(int i=0;i<n;i++)
34     {
35         memset(vis,0,sizeof(vis));
36         if(point(i)) res++;
37     }
38     return res;
39 }
40 
41 int main()
42 {
43     int u,k,v;
44     while(scanf("%d",&n)!=EOF)
45     {
46         for(int i=0;i<maxn;i++)//初始化清空vector 
47            Map[i].clear();
48         for(int i=0;i<n;i++)
49         {
50             scanf("%d:(%d)",&u,&k);  
51             for(int i=0;i<k;i++)
52             {
53                 scanf("%d",&v);
54                 Map[u].push_back(v);//u可以到v 
55                 Map[v].push_back(u);//v可以到u 
56             }
57         }
58         printf("%d\n",hungary()/2);
59     }
60     return 0;
61 }

 

posted on 2019-01-20 10:59  甜甜圈不懂巧克力的苦  阅读(149)  评论(0编辑  收藏  举报

导航