hdu 2444 The Accomodation of Students
http://acm.hdu.edu.cn/showproblem.php?pid=2444
一道二分匹配的题,不过要在匹配前判断是否能形成二分图!这是我baidu二分匹配找到的题,我当时看到要判断是否为二分图就感到有点蒙了,因为看完数据结构太久了,忘记了二分图有什么特性了。当时我还打算按进去看代码,结果一按进去就发现bfs和dfs。刚切完一道hk算法的我头昏脑胀的,果断关了网页。
在回宿舍的路上,我首先从bfs想到了可以判断是否有奇环。不过我想了好几个bfs的方法,都觉得复杂度挺大的,然后就直接抛弃了这个想法,另辟蹊径 !然后,我就发现,这些点和点间的关系有点像以前做过的一道并查集的题(poj 2492 A Bug's Life)。这样,好端端的朋友关系就因为要将人分成两堆而变成了敌对关系了!沿着这个思路,我打算先将人群分成好几组,然后在将他们根据敌对关系分成两份,最后再用匈牙利算法,因为规模才200,来解决余下的问题。
回到宿舍了,我把我思路先写下来,然后就敲了一个并查集上去。不过在我想其他几个函数的结构的时候,突然来了这样的思路。既然两两相连的点之间是敌对关系,那么,确认了一个点的分组,与它相连的点的状态不就确定了吗!然后,这就是一个类似于bfs的方法,将一堆人分成了两份,但是我的方法缺了bfs常用的队列,从而节省了空间。
分好组了,剩下的又是体力劳动了!不过比较囧的是,我的dfs里面居然因为打错了一个字母,搞到我debug了好几分钟....
不过搞掂这个以后,提交的就是1y的代码了~~~Yeah!对二分匹配更熟悉了!对hk算法的熟悉程度还需加强,搞几题来练练手先~
然后就是代码了:
View Code
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <vector> 5 6 using namespace std; 7 8 const int maxn = 205; 9 bool side[maxn], vis[maxn]; 10 int mt[maxn]; 11 vector<int> rel[maxn]; 12 13 int data(void){ 14 int n, m; 15 16 if (scanf("%d%d", &n, &m) == -1) return -1; 17 for (int i = 1; i <= n; i++){ 18 rel[i].clear(); 19 } 20 for (int i = 0; i < m; i++){ 21 int a, b; 22 23 scanf("%d%d", &a, &b); 24 rel[a].push_back(b); 25 rel[b].push_back(a); 26 } 27 28 return n; 29 } 30 31 bool attempt(int n){ 32 for (int i = 1; i <= n; i++){ 33 vis[i] = side[i] = false; 34 } 35 for (int i = 1; i <= n; i++){ 36 if (vis[i]){ 37 for (int j = 0; j < rel[i].size(); j++){ 38 if (vis[rel[i][j]]){ 39 if (side[rel[i][j]] == side[i]) return false; 40 } 41 else{ 42 vis[rel[i][j]] = true; 43 side[rel[i][j]] = !side[i]; 44 } 45 } 46 } 47 else{ 48 vis[i] = side[i] = true; 49 for (int j = 0; j < rel[i].size(); j++){ 50 if (vis[rel[i][j]]){ 51 if (side[rel[i][j]]) return false; 52 } 53 else{ 54 vis[rel[i][j]] = true; 55 side[rel[i][j]] = false; 56 } 57 } 58 } 59 } 60 61 return true; 62 } 63 64 bool dfs(int v){ 65 for (int i = 0; i < rel[v].size(); i++){ 66 if (!vis[rel[v][i]]){ 67 vis[rel[v][i]] = true; 68 if (mt[rel[v][i]] == -1 || dfs(mt[rel[v][i]])){ 69 mt[rel[v][i]] = v; 70 71 return true; 72 } 73 } 74 } 75 76 return false; 77 } 78 79 int cal(int n){ 80 int cnt = 0; 81 82 #ifndef ONLINE_JUDGE 83 for (int i = 1; i <= n; i++){ 84 printf("side %d : %d adj: ", i, side[i]); 85 for (int j = 0; j < rel[i].size(); j++){ 86 printf("%d ", rel[i][j]); 87 } 88 puts(""); 89 } 90 #endif 91 92 for (int i = 1; i <= n; i++) 93 mt[i] = -1; 94 for (int i = 1; i <= n; i++){ 95 memset(vis, false, sizeof(vis)); 96 if (side[i] && dfs(i)){ 97 cnt++; 98 #ifndef ONLINE_JUDGE 99 printf("yes\n"); 100 #endif 101 102 } 103 } 104 105 return cnt; 106 } 107 108 int main(){ 109 int n; 110 111 #ifndef ONLINE_JUDGE 112 freopen("in", "r", stdin); 113 #endif 114 115 while (~(n = data())){ 116 if (attempt(n)) printf("%d\n", cal(n)); 117 else printf("No\n"); 118 } 119 120 return 0; 121 }
——written by Lyon