poj 3487 & zoj 1576 稳定婚姻
两题都是基础题,不同的是 zoj 那题的男女可能重名。
Gale-Shapley 算法:
while ( 存在男人m是自由的 ) {
令w是m的还没求过婚的最高排名的女人
if ( w是自由的 ) m-w 配对
else {
取 w 的当前对象 m1
if ( w 更爱 m1 ) m保持自由
else m-w 配对 m1变成自由
}
}
poj 3487
const int N = 105; int n; int hm[N], hw[N]; //hm[i]为第i个男人的配偶 -1表示自由 int a[N][N], b[N][N], p[N]; //a[i][0~n]表示第i个男人心中的女人排名 //b[i][0~n]表示第i个女人心中的男人排名 string man[N], woman[N];//姓名 map<string, int> mp; //姓名->序号 set<int> st; //自由男人的集合 void read(){ mp.clear(); st.clear(); memset(hm, -1, sizeof hm); memset(hw, -1, sizeof hw); memset(p, 0, sizeof p); cin>>n; FOR(i, 0, n){ cin>>man[i]; mp[ man[i] ] = i; } FOR(i, 0, n){ cin>>woman[i]; mp[ woman[i] ] = i; } string str, s=""; int t; FOR(i, 0, n){ cin>>str; s = str[0]; t = mp[s]; FOR(j, 2, n+2){ s = str[j]; a[t][j-2] = mp[s]; } } FOR(i, 0, n){ cin>>str; s = str[0]; t = mp[s]; FOR(j, 2, n+2){ s = str[j]; b[t][j-2] = mp[s]; } } } void solve(){ FOR(i, 0, n) {st.insert(i); } //开始所有男人都是自由的 while( !st.empty() ){ //还有自由男人 int m = *st.begin(); st.erase(m); //任取一个 while(1){ int w = a[m][ p[m]++ ]; //未拒绝此男人的最优女人 int m1= hw[w], t; //此女人的配偶 if(m1==-1){ hw[w]=m; hm[m]=w; break; } //女人自由 FOR(i, 0, n) if(b[w][i]==m1 || b[w][i]==m) {t=b[w][i]; break;} //t是较优的男人 if(t==m){ //m更优 重新组合 hw[w]=m; hm[m]=w; hm[m1]=-1; st.insert(m1); break; } } } } int main(){ #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); #endif int T; cin>>T; while(T--){ read(); solve(); FOR(i, 0, n) cout<<man[i]<<' '<<woman[ hm[i] ]<<endl; cout<<endl; } return 0; }
zoj 1576
const int N = 505; int n; int hm[N], hw[N]; //hm[i]为第i个男人的配偶 -1表示自由 int a[N][N], b[N][N], p[N]; //a[i][0~n] 男i心中的女人次序 //b[i][0~n] 女i心中的男人次序 int c[N][N]; //c[i][j] 女i心中,男j的排名 string man[N], woman[N];//姓名 map<string, int> mp,wp; //姓名->序号 set<int> st; //自由男人的集合 void read(){ mp.clear(); wp.clear(); st.clear(); memset(hm, -1, sizeof hm); memset(hw, -1, sizeof hw); memset(p, 0, sizeof p); string str; FOR(i, 0, n){ cin>>man[i]; mp[ man[i] ] = i; if(i == 0) FOR(j, 0, n){ cin>>woman[j]; wp[ woman[j] ] = j; a[i][j] = j; } else FOR(j, 0, n){ cin>>str; a[i][j] = wp[str]; } } FOR(i, 0, n){ cin>>str; int t = wp[str]; FOR(j, 0, n){ cin>>str; int v = mp[str]; b[t][j] = v; c[t][v] = j; } } } void solve(){ FOR(i, 0, n) {st.insert(i); } //开始所有男人都是自由的 while( !st.empty() ){ int m = *st.begin(); st.erase(m); while(1){ int w = a[m][ p[m]++ ]; //未拒绝此男人的最优女人 int m1 = hw[w]; //此女人的配偶 if( m1 == -1 ){ hw[w]=m; hm[m]=w; break; } //女人无配偶 if(c[w][m] < c[w][m1]){ //女人有配偶但m更优 hw[w] = m; hm[m] = w; hm[m1] = -1; st.insert(m1); break; } } } } int main(){ #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); #endif while(cin>>n){ read(); solve(); FOR(i, 0, n) cout<<man[i]<<' '<<woman[ hm[i] ]<<endl; cout<<endl; } return 0; }