1、hdu 2444 The Accomodation of Students(判断二分图+最大匹配)(匈牙利模板)
题意:一共有n个学生,m对关系:A认识B。问能否将所有的人分成两批,每批之间的人都互相认识,如果可以,输出每批的人数。即判断是否为二分图,以及求二分图的最大匹配。
思路:判断是否为二分图(DFS或BFS);求二分图的最大匹配:匈牙利算法。
1 #include<iostream> 2 #include<queue> 3 using namespace std; 4 int n,m; 5 const int maxn = 210;//x集合和y集合总最大的点数 6 bool mp[maxn][maxn];//1表示该ij可以匹配 7 int cx[maxn];//记录x集合中匹配的y元素是哪一个 8 int cy[maxn];//记录y集合中匹配的x元素是哪一个 9 int vis[maxn];//标记该顶点是否访问过 10 int cntx; 11 bool dfs(int u) 12 { 13 for (int v = 1; v <= n; v++)//两个集合内共有n个元素 14 { 15 if (mp[u][v] && !vis[v]) 16 { 17 vis[v] = 1; 18 if (cy[v] == -1 || dfs(cy[v]))//)//如果y集合中的v元素没有匹配或者是v已经匹配,但是从cy[v]中能够找到一条增广路 19 { 20 cx[u] = v; cy[v] = u; 21 return 1; 22 } 23 } 24 } 25 return 0; 26 } 27 int maxmatch()//匈牙利算法主函数 28 { 29 int ans = 0; 30 memset(cx, 0xff, sizeof cx);//初始值为-1表示两个集合中都没有匹配的元素! 31 memset(cy, 0xff, sizeof cy); 32 for (int i = 1; i <= n; i++) 33 if (cx[i] == -1)//如果i未匹配 34 { 35 memset(vis, 0, sizeof(vis)); 36 ans += dfs(i); 37 } 38 return ans/2;//对两个部里的都匹配了,这样就相当于匹配了两次了 39 } 40 bool istwo() 41 {//判断是否为二分图 42 queue<int>q; 43 memset(vis, 0, sizeof(vis)); 44 q.push(1); 45 vis[1] = true; 46 while (!q.empty()) 47 { 48 int u = q.front(); 49 q.pop(); 50 for (int i = 1; i <= n; i++) 51 { 52 if (mp[u][i]) 53 { 54 if (vis[i] == 0) 55 { 56 if (vis[u] == 1) vis[i] = 2; 57 else vis[i] = 1; 58 q.push(i); 59 } 60 else 61 { 62 if (vis[i] == vis[u]) return false; 63 } 64 } 65 } 66 } 67 return true; 68 } 69 int main() 70 { 71 while (~scanf("%d%d", &n, &m)) 72 { 73 memset(mp ,0, sizeof(mp)); 74 while (m--) 75 { 76 int a, b; 77 scanf("%d%d", &a, &b); 78 mp[a][b] = mp[b][a] = 1; 79 } 80 if (!istwo()|| n == 1) 81 { 82 printf("No\n"); 83 } 84 else 85 { 86 int ans = maxmatch(); 87 printf("%d\n", ans); 88 } 89 } 90 91 return 0; 92 }