题意:男女各n人,进行婚配,对于每个人来说,所有异性都存在优先次序,即最喜欢某人,其次喜欢某人...输出一个稳定婚配方案。所谓稳定,就是指未结婚的一对异性,彼此喜欢对方的程度都胜过自己的另一半,那么这对异性就有私奔的可能性。
这里明显也是一个匹配问题,与最佳二分完美匹配所不同的是,二分匹配重在求最佳权值,而这里求的是满足彼此的要求。这里用到了Gale-Shapley算法。
算法学习:http://wenku.baidu.com/view/964a503843323968011c92c3.html
http://wenku.baidu.com/view/7aa841f2fab069dc502201cb.html
前者描述详细,值得一看;后者虽然描述不够清晰,但给出了优劣势的证明,并且对第一篇文章倒数第三段提到的“欺诈与博弈”给出了具体样例,可以借鉴。
先把代码贴出来,其实就是贪心的思路,模拟一下这种操作方式,O(n2)的复杂度,已经是输入复杂度了,不能再省了。
uva挂了,所以不保证code的正确性。
1 #include<iostream> 2 #include<cstdio> 3 #include<memory.h> 4 using namespace std; 5 #define Clear(f, nr) memset(f, nr, sizeof(f)) 6 const int SIZE = 1008; 7 const int INF = 1 << 30; 8 int n; 9 int men[SIZE][SIZE], wmen[SIZE][SIZE]; 10 int menChs[SIZE]; //女生的选择 11 int que[SIZE * SIZE]; 12 bool vis[SIZE][SIZE]; 13 void StableMarriage() 14 { 15 int front = 0, rear = 0; 16 Clear(menChs, -1); 17 Clear(vis, 0); 18 for(int i = 1; i <= n; i ++) 19 que[rear ++] = i; 20 21 while(front < rear) { 22 int tmp = que[front ++]; 23 for(int i = 1; i <= n; i ++) { 24 if(!vis[tmp][wmen[tmp][i]]) { 25 vis[tmp][wmen[tmp][i]] = 1; 26 if(menChs[wmen[tmp][i]] == -1) { 27 menChs[wmen[tmp][i]] = tmp; 28 break; //忘加一个break改了一个小时 29 } 30 else { 31 int mark = menChs[wmen[tmp][i]]; 32 if(men[wmen[tmp][i]][mark] < men[wmen[tmp][i]][tmp]) { 33 menChs[wmen[tmp][i]] = tmp; 34 que[rear ++] = mark; 35 break; 36 } 37 } 38 } 39 } 40 } 41 42 return ; 43 } 44 void Print() 45 { 46 for(int j = 1; j <= n; j ++) 47 for(int i = 1; i <= n; i ++) 48 if(menChs[i] == j) 49 cout << i << endl; 50 } 51 int main() 52 { 53 int T, x; 54 cin >> T; 55 int gg = 0; 56 while(T --) { 57 if(gg ++) puts(""); 58 cin >> n; 59 for(int i = 1; i <= n; i ++) 60 for(int j = 1; j <= n; j ++) 61 cin >> wmen[i][j]; //女生记邻接表 62 for(int i = 1; i <= n; i ++) 63 for(int j = 1; j <= n; j ++) { 64 cin >> x; 65 men[i][x] = n - j; //男生记邻接阵 权值 66 } 67 StableMarriage(); 68 Print(); 69 } 70 }